Prompt
How do I build SAML and OIDC support into one app?
Latest observation
To support both SAML and OIDC in one app, the cleanest approach is usually:
- Pick one internal identity model for your app
- Translate SAML and OIDC into that model
- Keep the protocol-specific logic at the edge
That way, your app doesn’t become “SAML-aware” and “OIDC-aware” everywhere—just your auth layer does.
1) Start with a shared internal auth model
Create a single user/session representation for your app, for example:
internal_user_idemailnameidp_type(samloroidc)idp_subject/nameidtenant/org- roles/groups/claims
- session state
Then map:
- OIDC claims → internal user
- SAML assertions → internal user
This prevents protocol-specific details from leaking into the rest of the app.
2) Decide your architecture
Option A: Use an identity broker / auth platform
Best if you want to avoid implementing protocol details yourself.
Examples:
- Auth0
- Okta
- Azure AD B2C / Entra
- Keycloak
- FusionAuth
- AWS Cognito (more limited for SAML/OIDC federation patterns, but usable)
In this setup:
- Your app speaks one protocol to the broker, often OIDC
- The broker handles:
- SAML SP/IdP flows
- OIDC flows
- user provisioning
- tenant routing
- MFA policies
This is usually the fastest and safest route.
Option B: Implement both in your app
This is feasible, but more work.
You’ll need:
- An OIDC client
- A SAML Service Provider
- A common account-linking / session layer
- Security handling for both protocols
This makes sense if:
- You need full control
- You have strict compliance constraints
- You can support the operational burden
3) Recommended login flow
For OIDC
Typical flow:
- User clicks “Sign in”
- Redirect to IdP authorization endpoint
- IdP authenticates user
- Your app receives an auth code
- Exchange code for tokens
- Validate ID token
- Create local session
For SAML
Typical flow:
- User clicks “Sign in”
- Redirect to IdP SSO URL with AuthnRequest
- IdP authenticates user
- IdP posts SAMLResponse to your ACS endpoint
- Validate signature, conditions, audience, issuer, time bounds
- Extract attributes
- Create local session
Internally, both should end with the same result:
- “authenticated user”
- local session cookie / token
- app authorization context
4) Unify identity mapping
You’ll need a way to associate external identities with internal accounts.
Good matching keys:
- OIDC:
sub+issuer - SAML:
NameID+IdP entityID
Better than using email alone, because email can change and may not be unique across all tenants.
A typical mapping table:
| internal_user_id | protocol | issuer/idp_entity | external_subject |
|---|---|---|---|
| 123 | oidc | https://login.example.com | abc123 |
| 123 | saml | https://idp.example.com | user@example.com |
If you support account linking, let one user connect multiple identity sources.
5) Handle tenant / organization routing
If this is multi-tenant B2B SaaS, you’ll likely need to determine:
- which customer org the user belongs to
- which IdP to use for that org
- whether to use SAML or OIDC for that org
Common approaches:
- Email domain discovery:
@customer.com→ redirect to correct IdP - Org-specific login URL:
/login/acme - IdP selection screen
- Invitation-based login
Store per-tenant config:
- protocol
- issuer / entityID
- client ID / metadata URL
- certificate / JWKS
- claim/attribute mappings
- default roles/groups
6) Security requirements you must get right
OIDC security
- Validate
iss,aud,exp,iat,nonce - Use PKCE for browser-based flows
- Check signature against JWKS
- Lock redirect URIs tightly
- Prefer authorization code flow
SAML security
- Validate XML signature
- Validate:
- issuer
- audience
- destination
- recipient
- assertion time conditions
- Prevent replay attacks
- Be careful with XML parser security issues
- Ensure the ACS endpoint is protected properly
For both
- Use HTTPS only
- Strong session cookies (
HttpOnly,Secure,SameSite) - Short-lived auth assertions, long-lived app session only if necessary
- Support logout carefully; single logout is often inconsistent across IdPs
- Log auth events for auditing
7) Normalize claims/attributes
Create a mapping layer from protocol attributes to your internal fields.
Example:
OIDC mapping
sub→ external_user_idemail→ emailgiven_name→ first_namefamily_name→ last_namegroups→ roles/groups
SAML mapping
NameID→ external_user_idmailoremailAddress→ emailFirstName→ first_nameLastName→ last_name- custom attribute
groups→ roles/groups
Be flexible because enterprise IdPs vary a lot.
8) Suggest a layered design
A good structure:
Layer 1: Protocol adapters
OidcAuthenticatorSamlAuthenticator
Layer 2: Identity normalization
- converts protocol-specific claims into a common
ExternalIdentity
Layer 3: Account linking / provisioning
- find existing local user
- create if allowed
- link multiple identities
Layer 4: Session issuance
- create app session cookie / JWT
- apply app roles and tenant context
This keeps complexity manageable.
9) If you want to simplify, make your app OIDC-first
A very common pattern is:
- Support OIDC natively
- Support SAML indirectly through an identity broker
This gives you:
- one auth integration in the app
- SAML compatibility for enterprise customers
- easier maintenance
If enterprise customers require SAML, you can federate:
- SAML IdP → broker → your app via OIDC
That’s often the best balance of compatibility and simplicity.
10) Practical implementation choices
If using a framework/library
- Node.js:
openid-clientfor OIDC,passport-samlorsamlifyfor SAML - Python:
Authlibfor OIDC,python3-saml/ OneLogin toolkit for SAML - Java: Spring Security OIDC + SAML modules
- .NET: Microsoft Identity Web for OIDC, Sustainsys.Saml2 for SAML
- Go: OIDC libraries plus SAML libraries, though SAML ergonomics are rougher
If using a broker
- Configure your app as an OIDC client
- Configure the broker with:
- OIDC upstream IdPs
- SAML upstream IdPs
- Use standard OIDC login in the app
11) Suggested rollout plan
- Implement OIDC login first
- Build internal identity/session normalization
- Add SAML support behind the same abstraction
- Add tenant-specific IdP configuration
- Add account linking and provisioning
- Add audit logs, admin tools, and support diagnostics
- Test with real enterprise IdPs:
- Okta
- Azure AD / Entra
- Google Workspace
- Ping
- OneLogin
12) A good default recommendation
If you’re starting from scratch:
- Use OIDC as your app’s primary protocol
- Use an identity broker if you need SAML support
- Normalize all identities into one internal user model
- Avoid protocol logic outside the auth layer
That architecture will save you a lot of pain.
If you want, I can also give you:
- a reference architecture diagram,
- a database schema for linking SAML/OIDC identities, or
- sample code for Node/Python/Java/.NET.