Prompt
What's the best way to handle SSO, SCIM, and RBAC together in a SaaS app?
Latest observation
The best way is to treat them as three layers of the same identity system rather than separate features:
-
SSO = authentication
- Proves who the user is.
- Commonly via SAML or OIDC.
- Should create or link a user in your app, but not directly grant app permissions beyond a basic default.
-
SCIM = provisioning and lifecycle
- Creates, updates, deactivates users and groups from the customer’s IdP.
- Use it to keep your app’s user directory in sync.
- Let SCIM manage:
- user creation
- name/email updates
- deactivate/reactivate
- group membership
- optional role assignment mappings
-
RBAC = authorization
- Determines what the user can do inside your app.
- Should be enforced from your app’s internal permission model, not directly from the IdP.
- Use roles as a stable abstraction:
org_adminbilling_adminmemberread_only
- Map IdP groups or SCIM groups to these roles where appropriate.
Recommended architecture
1) Maintain an internal identity model
Have internal objects like:
Organization / TenantUserGroupRoleMembershipExternalIdentity(IdP subject / SCIM identifier)
This gives you a durable app-side source of truth for authorization.
2) Separate authentication from authorization
- On SSO login, verify the assertion/token.
- Resolve the user to an internal account.
- Then load roles/permissions from your database.
- Do not trust SSO alone for fine-grained access.
3) Use SCIM for account and group sync
SCIM should be the primary way enterprise customers manage:
- user onboarding/offboarding
- group assignment
- sometimes default roles
If SCIM says a user is deprovisioned, immediately disable access, even if they can still technically authenticate.
4) Map groups to roles
A common pattern:
- IdP group
Finance-Team→ app rolebilling_admin - IdP group
All-Employees→ app rolemember
Keep the mapping:
- explicit
- tenant-specific
- editable by admins
- auditable
Avoid hardcoding assumptions across customers.
5) Prefer role templates over direct permission assignment
If you let SCIM assign permissions directly, things get messy. Better:
- SCIM syncs group membership
- groups map to roles
- roles map to permissions
This keeps your system understandable and portable.
Practical rules that help
- SSO should not create privilege by itself
- At most, it should auto-provision a user into a default role.
- SCIM should be authoritative for existence and group membership
- If SCIM disables a user, access is revoked.
- RBAC should be authoritative for app behavior
- Even if a user is authenticated, every protected action checks roles/permissions.
- Support multiple identity sources
- Some customers will use SSO only.
- Some will use SSO + SCIM.
- Some may want local admins too.
Good onboarding flow
- Customer configures SSO.
- Customer configures SCIM.
- First SCIM push creates users/groups.
- First login via SSO links the identity.
- Admin maps groups to roles.
- App enforces permissions based on internal RBAC.
Common pitfalls
- Using the IdP group name as the app’s permission model directly
- Letting SSO create users without a tenant boundary
- Not handling deprovisioning immediately
- Mixing “who the user is” with “what the user can do”
- No audit trail for group/role changes
- Assuming email is a stable identifier
- Not supporting just-in-time provisioning fallback when SCIM isn’t enabled
Best practice in one sentence
Use SSO to authenticate users, SCIM to provision and sync identities/groups, and RBAC inside your app to authorize actions, with a tenant-scoped mapping between external groups and internal roles.
If you want, I can also sketch a reference data model or request/auth flow diagram for this setup.