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 laterPermission Statuses
none (No Permission Record)
- Meaning: User has never attempted to access this app
- What happens during OAuth: SSO creates a
pendingrecord 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
rolefield 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
- Login to SSO Admin Panel
- Navigate to Users list
- Click on a user to view details
- Scroll to "Application Access" section
- See all integrated apps and user's permission status for each
Granting Access
- In user's "Application Access" section
- Find app with status "revoked" or "pending"
- Select role: "user" or "admin"
- Click "Grant Access" or "Approve"
- User can now complete OAuth flow
Changing Role
- Find app with status "approved"
- Use role dropdown to change between "user" and "admin"
- Change applies immediately
- Note: Existing tokens still have old role until refresh
Revoking Access
- Find app with status "approved"
- Click "Revoke Access" button
- Confirm in dialog
- User's permission status set to "revoked"
- 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 OKRevoke 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 OKSecurity 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
- Admin Approval Process - How SSO admins manage access
- Authentication Guide - OAuth 2.0 flow details
- Quick Start Guide - Integration tutorial
- API Reference - Complete endpoint documentation