Prompt
I'm building a product with multiple IdPs per customer. How should I design the auth layer?
Latest observation
If you need multiple IdPs per customer, the safest pattern is to treat your app as the Identity Broker / Authorization Server boundary, and keep each customer’s IdPs as upstream authentication sources.
Recommended design
1) Separate authentication from authorization
- IdPs authenticate the user
- Your app authorizes the user based on:
- tenant/customer membership
- roles/permissions in your app
- optional claims from the IdP
Do not let the IdP directly become your authorization model unless you fully control it end-to-end.
2) Model tenancy explicitly
Have at least these concepts:
- Customer/Tenant
- Identity Provider connection
- User
- User identity link (user ↔ IdP subject)
- Session / token
- App role / permission
Example relationships:
- Tenant A can have Okta + Azure AD
- Tenant B can have Google Workspace + Entra ID + an internal SAML IdP
- One user can have multiple linked identities across IdPs
- One IdP connection can map to one tenant, or in some cases a shared enterprise IdP can map to several tenants with strict rules
3) Use an identity broker pattern
Instead of integrating your app directly with every IdP flow, build or use a broker layer that:
- handles OIDC/SAML connections
- normalizes claims into one internal user model
- performs account linking
- issues your own app session/JWT
This gives you one consistent auth surface even if upstream IdPs vary.
4) Support account linking and tenant scoping
You’ll need to decide how a login maps to an internal account.
Typical matching order:
- Tenant selected or inferred
- IdP connection determined for that tenant
- External identity subject (
iss+subfor OIDC, NameID/entity IDs for SAML) - Optional email match, but only if trusted and verified
- If ambiguous, require admin or user-led linking
Important:
- Don’t auto-merge users across IdPs just because email matches
- Use stable, provider-issued identifiers as the primary key
- Keep a separate linking workflow for account takeover safety
5) Issue your own tokens/sessions
After upstream login:
- verify the IdP response
- map to internal user
- apply tenant context
- mint your own:
- session cookie, or
- short-lived access token + refresh token
Your token should contain:
- your user ID
- tenant ID
- roles/entitlements
- session ID
- maybe the upstream IdP connection ID
Avoid passing raw upstream tokens throughout your system unless you truly need them.
6) Make tenant selection explicit in the UX
Common patterns:
- user enters email/domain first, then you route them to the right IdP
- user selects their org from a branded login page
- deep link includes tenant slug
- if a user belongs to multiple tenants, let them choose after login
This matters a lot when one user can authenticate via multiple IdPs.
Suggested architecture
Auth flow
- User hits app
- App determines tenant context
- App redirects to the correct IdP connection
- Upstream IdP authenticates user
- Callback to your broker
- Broker validates response
- Broker finds or links internal user
- Broker applies tenant authorization
- Broker issues app session/token
- App enforces permissions from your own auth layer
Data model sketch
tenants
- id
- name
- slug
- settings
identity_providers
- id
- tenant_id
- type (
oidc,saml) - issuer / entity_id
- metadata
- status
users
- id
- primary_email
- display_name
- status
user_identities
- id
- user_id
- tenant_id
- identity_provider_id
- subject_identifier
- email_at_login
- verified
- last_login_at
memberships
- id
- user_id
- tenant_id
- role
sessions
- id
- user_id
- tenant_id
- expires_at
- revoked_at
Security rules to follow
- Validate issuer, audience, nonce/state, signature, and token expiration
- Pin each IdP connection to a tenant
- Never trust unverified email as the only identity signal
- Require MFA/step-up auth for sensitive operations if possible
- Support logout and token revocation
- Log every auth event with tenant, IdP, subject, and session ID
- Protect against mix-up attacks and tenant confusion
- If using SAML, be strict on ACS URL, audience, and destination
If you need to support many enterprise customers
Consider an auth system with:
- OIDC and SAML support
- per-tenant IdP configuration
- JIT provisioning
- SCIM for lifecycle management
- directory sync for groups/roles
- admin console for IdP setup and testing
This can be built in-house, but many teams use an IdP broker or customer identity platform to reduce risk and maintenance.
Practical recommendation
For most SaaS products with multi-IdP-per-customer support, the cleanest approach is:
- Tenant-aware login
- IdP connections stored per tenant
- Brokered auth
- Internal user + identity-link model
- Your own app session/token issuance
- Authorization entirely in your app
If you want, I can also give you:
- a reference architecture diagram,
- a database schema, or
- a login flow for OIDC + SAML with multiple IdPs per tenant.