Prompt
Are you able to help me design SSO for a SaaS app with existing password auth, multiple customers, and a need for SCIM provisioning? I need a practical recommendation on SAML vs OIDC, how to map users to tenants and roles, and how to keep setup simple for enterprise admins.
Latest observation
Yes — I can help with that.
For a SaaS app with:
- existing password auth,
- multiple customer tenants,
- and SCIM provisioning,
the practical approach is usually:
- Use OIDC as the default SSO protocol if you can
- Support SAML if your enterprise customers require it
- Use SCIM for provisioning/deprovisioning and group sync
- Model identity around tenant membership, not global users
Here’s a recommended design.
1) SAML vs OIDC: practical recommendation
Default recommendation: OIDC
If you’re building a new enterprise SSO integration today, OIDC is usually the better default because:
- simpler implementation than SAML
- easier debugging
- JSON/JWT-based, more developer-friendly
- works well for modern IdPs
- better fit if your app already has web + API auth
Still support SAML if enterprise demand is high
Many large enterprises still expect SAML, and some IdPs or admins are more comfortable configuring it.
Best practical answer
If you can afford both:
- OIDC as preferred/first-class
- SAML as compatibility layer
If you must choose one:
- choose OIDC unless your target buyers are overwhelmingly enterprise IT teams who explicitly demand SAML
2) Identity model: separate global users from tenant memberships
For a multi-tenant SaaS, do not treat “user” and “tenant access” as the same thing.
Suggested model
User
Represents the person globally in your system.
Example fields:
user_idemailnameauth_methods(password, google, oidc, saml)status
Tenant
Represents the customer organization/account.
tenant_idnamestatus
Membership
Represents the user’s access in a specific tenant.
membership_iduser_idtenant_idrolesource(manual, sso, scim)idp_subject/external_identity_idgroupsoptionallystatus
This gives you flexibility for:
- one person in multiple customers
- different roles per tenant
- mixed auth methods
- SCIM-driven lifecycle management
3) How SSO should map users to tenants
Recommended rule
SSO should authenticate the user, then resolve:
- Which tenant is this login for?
- Is the user allowed in that tenant?
- What role should they have?
Tenant selection options
There are three common patterns:
A. Tenant picked before login
User goes to:
customerA.yourapp.com- or
yourapp.com/login?tenant=customerA
This is simplest for routing and best for enterprise.
B. Email domain discovery
User enters email, and you route based on domain:
@acme.com→ Acme tenant
Good UX, but not always reliable because:
- contractors may use external emails
- some customers have multiple domains
- one domain may map to multiple tenants in edge cases
C. IdP-initiated login with tenant binding
Enterprise admin starts login from the IdP tile. You already know the tenant from the app config.
This is common for SAML and increasingly for OIDC enterprise setups.
Best practical setup
Use:
- tenant-specific login entry points
- plus email domain discovery
- plus IdP-initiated support
That gives good UX and enterprise friendliness.
4) How to map SSO users to internal users
Use a stable external identity key.
For OIDC
Map by:
issuer + subject(iss + sub)
This is the most reliable identity key.
For SAML
Map by:
- NameID if stable, but don’t rely on it alone
- better: a persistent unique attribute if the IdP can send one
- store the IdP entity ID + NameID/subject-like identifier
Recommended matching logic
When a user logs in:
- Find a membership by
(tenant_id, issuer, subject)or equivalent - If found, log them in
- If not found:
- if auto-provisioning is enabled, create user + membership
- otherwise deny and prompt admin intervention
5) Role mapping strategy
Keep roles simple at first.
Suggested internal roles
- Owner/Admin
- Member
- Read-only or Viewer
Enterprise mapping patterns
Option 1: One default role for all SSO users
Simplest setup:
- all SSO users get
Member - first user or SCIM-created admin gets
Admin
This is easiest for customers and reduces support burden.
Option 2: Role by group claim
If IdP sends groups, map:
App-Admins→ AdminApp-Users→ MemberApp-Viewers→ Viewer
This is common and practical.
Option 3: Fine-grained RBAC
Only if your app truly needs it. Otherwise it adds complexity quickly.
Best practice
- Make tenant-level role assignment the primary model
- Treat IdP groups as an input to role assignment
- Avoid making authorization depend on many external groups in real time
6) SCIM provisioning design
SCIM should manage:
- user creation
- deactivation
- basic profile updates
- group membership if supported
What SCIM should do in your system
For each tenant, store a SCIM integration with:
tenant_ididp/connector name- SCIM bearer token or credential
- mapping config
SCIM user lifecycle
When SCIM User is created:
- create global user if needed
- create membership in that tenant
- assign role based on SCIM group mapping or default role
When SCIM User is deactivated:
- disable membership
- optionally disable global user if no active memberships remain
When SCIM User is updated:
- update name/email
- keep identity mapping stable
SCIM group handling
If the IdP supports group push:
- map groups to roles or app groups
- don’t require customers to manually manage both group mappings and roles in too many places
7) Keep setup simple for enterprise admins
This is very important.
Make onboarding a 3-step flow
Step 1: Create tenant SSO config in your app
Customer admin enters:
- domain name
- IdP type: Okta / Entra / Ping / Google / Other
- protocol: OIDC or SAML
- optional SCIM enablement
You generate:
- ACS/redirect URLs
- Entity ID / client metadata
- SCIM base URL
- SCIM token
Step 2: Admin configures IdP
Provide copy/paste setup instructions:
- single redirect URL
- single identifier/issuer
- SCIM endpoint/token
- optional group claims
Step 3: Test and activate
Offer:
- “Test SSO”
- “Test SCIM”
- “Activate for this tenant”
Reduce choices
To keep it simple:
- default to one SSO connection per tenant
- default role for new users
- optional group-to-role mapping
- SCIM optional but recommended
8) Recommended login behavior
Password auth coexistence
Since you already have password auth, support both:
- local login for small customers / fallback
- SSO for enterprise tenants
Good login rules
- If tenant has SSO enforced, route users to SSO
- If tenant does not enforce SSO, allow both password and SSO
- Let admins disable password auth per tenant if they want
Important
Don’t create duplicate accounts for the same email across auth methods if you can avoid it. Prefer one user record with multiple auth identities linked.
9) Suggested policy decisions
Here’s a good default policy set:
Identity
- Global user record
- tenant membership table
- unique external identity per IdP per tenant
SSO
- Prefer OIDC
- Support SAML
- Tenant-scoped IdP connection
Provisioning
- SCIM creates/deactivates memberships
- SSO can JIT-provision if allowed
- SCIM is source of truth for lifecycle in enterprise tenants
Authorization
- Internal roles: Admin, Member, Viewer
- Optional group-to-role mapping
- Default role for new users
Tenant routing
- Dedicated tenant URL and/or email domain discovery
- Admin-configured tenant SSO connection
10) A practical “best balance” architecture
If you want a concrete recommendation:
Use this design
- OIDC for SSO
- SAML support for compatibility
- SCIM 2.0 for provisioning
- tenant-based identity model
- user-to-tenant membership table
- group-based role mapping
- JIT provisioning only when SCIM is not enabled
- password auth retained as fallback unless tenant enforces SSO
Why this works
- simple enough for admins
- supports enterprise requirements
- doesn’t overcomplicate your auth model
- scales to multiple customers and multiple IdPs
- avoids fragile identity assumptions
11) Common pitfalls to avoid
- Using email as the sole identity key
- Making one user belong to only one tenant
- Treating SCIM as optional “nice-to-have” but not aligning it with auth
- Having too many roles or too much group complexity early
- Requiring admin support for every user invite
- Not storing stable IdP identifiers
- Letting password and SSO create duplicate users with the same email
12) My short recommendation
If you want the shortest practical answer:
- Choose OIDC as your primary SSO protocol
- Add SAML if enterprise customers ask for it
- Use SCIM for provisioning and deprovisioning
- Model access as user + tenant membership + role
- Map identities using stable IdP subject/issuer identifiers
- Keep admin setup to one IdP connection, one SCIM config, and optional group-to-role mapping
If you want, I can also provide:
- a reference data model,
- sequence diagrams for login + SCIM flows, or
- a step-by-step admin setup UX for Okta/Entra-style enterprise onboarding.