App Permissions

API Version: 5.24.0

Overview

DoneIsBetter SSO implements app-level permission control to manage which users can access which applications. This is a centralized authorization layer separate from authentication.

Key Concepts:

  • Authentication - User proves their identity (login)
  • Authorization - SSO decides if user can access specific app
  • App Permission - Per-user, per-app access control record
  • Permission Status - Current state: none, pending, approved, or revoked
  • App Role - User's role within app: user or admin

Permission Lifecycle

           ┌──────────┐
           │   none   │  Initial state - no permission record exists
           └────┬─────┘
                │
                │ User attempts OAuth login
                ↓
           ┌──────────┐
           │ pending  │  Auto-created on first login attempt
           └────┬─────┘  Status: User waiting for admin approval
                │
                │ SSO Admin grants access
                ↓
           ┌──────────┐
           │ approved │  Status: User can access app
           └────┬─────┘  Role: 'user' or 'admin'
                │
                │ SSO Admin revokes access
                ↓
           ┌──────────┐
           │ revoked  │  Status: Access denied
           └──────────┘  Can be re-approved later

Permission Statuses

none (No Permission Record)

  • Meaning: User has never attempted to access this app
  • What happens during OAuth: SSO creates a pending record automatically
  • User experience: First login attempt shows "Access Pending Approval" message
  • Next step: SSO admin reviews and approves/denies

pending (Awaiting Admin Approval)

  • Meaning: User requested access, waiting for SSO admin decision
  • Database record:
    {
      userId: "550e8400-e29b-41d4-a716-446655440000",
      clientId: "your-app-client-id",
      status: "pending",
      role: "none",
      createdAt: "2025-10-15T12:00:00.000Z",
      updatedAt: "2025-10-15T12:00:00.000Z"
    }
  • User experience: SSO shows: "Your access request is pending approval. An admin will review your request shortly."
  • OAuth flow: Authorization stops at permission check, no code issued
  • How to approve: SSO admin uses Admin Panel → Users → App Permissions → Grant Access

approved (Access Granted)

  • Meaning: User has active permission to access app
  • Database record:
    {
      userId: "550e8400-e29b-41d4-a716-446655440000",
      clientId: "your-app-client-id",
      status: "approved",
      role: "admin",  // or "user"
      grantedAt: "2025-10-15T14:30:00.000Z",
      grantedBy: "admin-user-uuid",
      createdAt: "2025-10-15T12:00:00.000Z",
      updatedAt: "2025-10-15T14:30:00.000Z"
    }
  • User experience: OAuth completes successfully, user redirected to app
  • Token payload: ID token includes role field from permission record
  • Duration: Indefinite until revoked or role changed

revoked (Access Removed)

  • Meaning: User previously had access but it was removed
  • Database record:
    {
      userId: "550e8400-e29b-41d4-a716-446655440000",
      clientId: "your-app-client-id",
      status: "revoked",
      role: "none",  // Cleared when revoked
      revokedAt: "2025-10-15T16:00:00.000Z",
      revokedBy: "admin-user-uuid",
      createdAt: "2025-10-15T12:00:00.000Z",
      updatedAt: "2025-10-15T16:00:00.000Z"
    }
  • User experience: SSO shows: "Your access to this application has been revoked. Contact support if you believe this is an error."
  • Existing tokens: Remain valid until expiry (1 hour for access tokens)
  • Can be re-approved: Yes, SSO admin can grant access again

App-Level Roles

App permissions include a role field that defines the user's permissions within your app (not SSO itself).

Role: "user" (Standard Access)

  • Default role for most users
  • Can access app features but not admin functions
  • Your app receives role: "user" in ID token payload
  • Example use: Regular users in Launchmass can view/edit their own pages

Role: "admin" (Elevated Access)

  • Granted by SSO admin for trusted users
  • Can access app's administrative features
  • Your app receives role: "admin" in ID token payload
  • Example use: Admins in Launchmass can manage all users and organizations

⚠️ Important Distinction:
SSO Admin - Manages SSO service itself (grants app permissions)
App Admin - User with role: "admin" for a specific app (manages app features)

These are separate! An SSO admin might not have any app permissions, and an app admin might not be an SSO admin.

Handling Permissions in Your App

1. During OAuth Callback

Extract role from ID token after token exchange:

// After POST /api/oauth/token
const { id_token } = await tokenResponse.json();
const jwt = require('jsonwebtoken');
const userInfo = jwt.decode(id_token);

// Store in your app's session
req.session.userId = userInfo.sub;
req.session.email = userInfo.email;
req.session.role = userInfo.role;  // "user" or "admin"

// Route user based on role
if (userInfo.role === 'admin') {
  res.redirect('/admin/dashboard');
} else {
  res.redirect('/dashboard');
}

2. Protecting Admin Routes

Use role from session to guard admin-only features:

// Middleware for admin-only routes
function requireAppAdmin(req, res, next) {
  if (req.session.role !== 'admin') {
    return res.status(403).json({
      error: 'Admin access required'
    });
  }
  next();
}

// Use on admin routes
app.get('/admin/users', requireAppAdmin, (req, res) => {
  // Only app admins can access
});

3. Periodic Permission Validation

Check if user still has access (in case of revocation):

// Run periodically or on sensitive operations
async function validateAppAccess(req, res, next) {
  const accessToken = req.session.accessToken;
  
  // Validate with SSO
  const validation = await fetch('https://sso.doneisbetter.com/api/public/session', {
    headers: {
      'Authorization': `Bearer ${accessToken}`
    }
  });
  
  if (!validation.ok) {
    // Permission revoked or token expired
    req.session.destroy();
    return res.redirect('/login');
  }
  
  next();
}

// Use on critical operations
app.post('/admin/delete-user', requireAppAdmin, validateAppAccess, async (req, res) => {
  // Double-check user still has admin access
});

Managing Permissions (SSO Admins)

SSO administrators manage app permissions through the Admin Panel at https://sso.doneisbetter.com/admin

Viewing User's App Permissions

  1. Login to SSO Admin Panel
  2. Navigate to Users list
  3. Click on a user to view details
  4. Scroll to "Application Access" section
  5. See all integrated apps and user's permission status for each

Granting Access

  1. In user's "Application Access" section
  2. Find app with status "revoked" or "pending"
  3. Select role: "user" or "admin"
  4. Click "Grant Access" or "Approve"
  5. User can now complete OAuth flow

Changing Role

  1. Find app with status "approved"
  2. Use role dropdown to change between "user" and "admin"
  3. Change applies immediately
  4. Note: Existing tokens still have old role until refresh

Revoking Access

  1. Find app with status "approved"
  2. Click "Revoke Access" button
  3. Confirm in dialog
  4. User's permission status set to "revoked"
  5. Note: Existing access tokens remain valid until expiry (max 1 hour)

App Permissions API

SSO provides REST APIs for programmatic permission management.Requires SSO admin authentication (admin session cookie).

Get User's Permissions

GET https://sso.doneisbetter.com/api/admin/app-permissions/[userId]
Cookie: admin-session=...

// Response:
{
  userId: "550e8400-e29b-41d4-a716-446655440000",
  apps: [
    {
      clientId: "launchmass-client-id",
      name: "Launchmass",
      description: "Landing page builder",
      role: "admin",
      status: "approved",
      grantedAt: "2025-10-15T14:30:00.000Z",
      grantedBy: "admin-uuid"
    },
    {
      clientId: "messmass-client-id",
      name: "Messmass",
      description: "Messaging platform",
      role: "none",
      status: "pending",
      createdAt: "2025-10-15T16:00:00.000Z"
    }
  ]
}

Grant/Approve Access

POST https://sso.doneisbetter.com/api/admin/app-permissions/[userId]
Cookie: admin-session=...
Content-Type: application/json

{
  "clientId": "your-app-client-id",
  "role": "user",  // or "admin"
  "status": "approved"
}

// Response: 200 OK
{
  success: true,
  permission: { ...updated permission record... }
}

Update Role

PATCH https://sso.doneisbetter.com/api/admin/app-permissions/[userId]
Cookie: admin-session=...
Content-Type: application/json

{
  "clientId": "your-app-client-id",
  "role": "admin"  // Change from "user" to "admin"
}

// Response: 200 OK

Revoke Access

DELETE https://sso.doneisbetter.com/api/admin/app-permissions/[userId]
Cookie: admin-session=...
Content-Type: application/json

{
  "clientId": "your-app-client-id"
}

// Response: 200 OK

Security Considerations

  • Apps Cannot Grant Self-Access

    Only SSO admins can approve app permissions. Apps cannot call permission APIs with their OAuth credentials.

  • Token Role is Snapshot

    Role in ID token is captured at token issuance. If admin changes role, user needs to refresh token to see new role.

  • Revocation Not Immediate

    Revoking access doesn't invalidate existing tokens. They expire naturally (1 hour). Implement periodic validation for critical operations.

  • Validate Role Server-Side

    Don't trust client-side role checks. Always verify role from your backend session before granting admin features.

  • Audit Permission Changes

    All permission grants/revokes are logged with admin identity and timestamp in SSO database.

Related Documentation