Roles and Permissions
Roles and permissions structure
In our application using SuperTokens, we maintain a clear separation between roles and permissions:
Roles
- Definition: Roles represent user types or job functions (e.g.,
admin,coder,reviewer,validator) - Assignment: Roles are assigned per
[user, tenantId]pair - a single user can have different roles in different tenants - Multi-tenancy: A user can belong to multiple tenants, with one role per tenant
- Purpose: Group users by their function or responsibility level within a specific tenant
- Naming: Use nouns describing the user's role (e.g.,
tim,internal-dim)
Permissions
- Definition: Permissions are commands or actions that users can perform
- Assignment: Permissions are assigned to roles (not directly to users)
- Purpose: Define granular capabilities and operations
- Naming: Use action verbs describing what can be done (e.g.,
c.ms.vcfor validate-coding,c.ms.tacfor trigger-ai-coding)
Disjoint Sets Principle
Roles ∩ Permissions = ∅
Roles and permissions must be completely separate - no name should exist in both sets. This prevents ambiguity and ensures clarity:
- ❌ Bad: Having both a role
validatorand a permissionvalidate - ✅ Good: Role
validatorwith permissionc.ms.vms(validate-medical-stay)
This separation ensures:
- Clear distinction between "who someone is" (role) vs "what they can do" (permission)
- Unambiguous authorization checks in code
- Easier permission management and auditing
Implementation Flow
[User, TenantId] → assigned to → Role → contains → Permission(s) → checked in codeExample:
A user john.doe@example.com belongs to multiple tenants with different roles:
Tenant A (Hospital A):
- User:
john.doe@example.com - TenantId:
tenant-hospital-a - Role:
internal-dim - Permissions:
c.vp,c.ms.tac,c.ms.vc,c.ms.rc
Tenant B (Hospital B):
- User:
john.doe@example.com - TenantId:
tenant-hospital-b - Role:
admin - Permissions:
c.vp,c.ms.tac,c.ms.vc,c.ms.rc,c.ms.vms,st.vp, ...
The same user has different capabilities depending on which tenant context they're operating in.
Permissions Naming Convention
Problem: JWT Token Size Limits
When using SuperTokens with role-based permissions, all permissions assigned to a user's roles are stored in the JWT access token payload. JWT tokens have practical size limits (typically 4-8KB) imposed by:
- HTTP header size limits
- Cookie size limits
- Browser and server configurations
When the total character count of all permissions exceeds ~1000 characters, the JWT token becomes too large, causing the SuperTokens provider to crash or fail silently.
Example: 21 verbose permissions like coding.medical-stay.view-flag-only-parallel total ~996 characters, approaching this limit.
Solution: Abbreviated Permission Names
To overcome JWT size limits while maintaining granular permissions, we use abbreviated permission codes.
Naming Convention
Format: <domain>.<subdomain>.<action>
Each segment is abbreviated using initials or short identifiers:
- Domain: First letter(s) of the main service/module
- Subdomain: First letter(s) of each word in the resource
- Action: First letter(s) of each word in the action
Examples
| Full Permission | Abbreviated | Breakdown |
|---|---|---|
coding.view-page | c.vp | coding.view-page |
coding.medical-stay.view-flag-only-parallel | c.ms.vfop | coding.medical-stay.view-flag-only-parallel |
coding.medical-stay.trigger-ai-coding | c.ms.tac | coding.medical-stay.trigger-ai-coding |
coding.medical-stay.can-cancel-action.from-validated | c.ms.cca.fv | coding.medical-stay.can-cancel-action.from-validated |
screenflow.view-page | s.vp | screenflow.view-page |
settings.view-page | st.vp | stettings.view-page |
Maintenance
Keep a reference table mapping abbreviated codes to their full descriptive names for clarity.