Enterprise SSO: SAML, OIDC Federation, and SCIM
Enterprise customers will ask for SAML 2.0 SSO and SCIM provisioning before they sign. Offer OIDC federation too, but expect most identity teams to choose SAML for years. SAML is where in-house builds get breached, so treat the XML layer as hostile input.
How a connection works
Each enterprise customer is a tenant with one or more connections. A connection stores:
- Protocol (SAML or OIDC) and the IdP's metadata: entity ID, SSO URL, signing certificates
- Your SP entity ID and assertion consumer service (ACS) URL for that connection
- Verified email domains that route to it
- Attribute mapping (email, name, groups, employee ID)
- Enforcement: SSO required, or allowed alongside other methods
- Provisioning mode: just-in-time, SCIM, or both
Routing users to the right IdP
- The user enters an email on your identifier-first screen.
- You look up the domain. If it belongs to a verified SSO connection, redirect to that IdP.
- Require proof of domain ownership (a DNS TXT record) before a tenant can claim a domain. Otherwise one customer can redirect another company's employees to an IdP it controls.
SAML validation checklist
GitHub's security team disclosed authentication bypasses in the widely used ruby-saml library in March 2025 (CVE-2025-25291 and CVE-2025-25292), caused by two XML parsers reading the same document differently. (NVD) That class of bug, signature wrapping, has hit many SAML libraries. Use a maintained library, keep it patched, and verify that it enforces every item below:
- Parse XML with DTDs and external entities disabled (blocks XXE).
- Validate the signature with the certificate configured for this connection only. Never trust a certificate embedded in the message.
- Confirm the signed element is exactly the assertion you then read: check the signature's reference ID and reject documents with more than one assertion.
- Check
Issuerequals the connection's IdP entity ID. - Check
Audienceequals your SP entity ID, andDestinationandRecipientequal your ACS URL. - Enforce
NotBeforeandNotOnOrAfterwith at most a few minutes of clock skew. - For SP-initiated logins, check
InResponseTomatches a request you sent and have not seen answered. - Cache assertion IDs until they expire and reject repeats (replay protection).
- Accept only strong signature algorithms (RSA-SHA256 or better). Reject SHA-1.
- Treat IdP-initiated SSO as higher risk: it has no request to match, so allow it only when a customer needs it, and still enforce replay protection.
Add a test suite of malicious SAML responses (wrapped signatures, comments inside NameID, duplicate assertions, unsigned assertions inside a signed response) and run it on every library upgrade.
Certificate rotation
IdPs rotate signing certificates. Let each connection hold two certificates at once, warn admins before expiry, and support metadata URLs that refresh automatically.
OIDC federation
For IdPs that support it, OIDC is simpler and safer than SAML: your server is an OIDC client of the customer's IdP. Apply the same rules as Chapter 9 from the client side: PKCE, state, nonce, iss checks, and ID token validation against the IdP's JWKS.
SCIM provisioning
SCIM 2.0 (RFC 7643 and RFC 7644) lets the customer's IdP create, update, and deactivate users in your system.
- Implement
/Usersand/GroupswithGET,POST,PUT,PATCH, and filtering byuserNameandexternalId. - Authenticate each tenant's SCIM client with its own long, revocable bearer token or OAuth client.
- On deactivation, revoke every session and refresh token for that user immediately. This is the main reason enterprises want SCIM.
- Test against the major IdPs' SCIM clients; each has quirks in PATCH syntax.
Just-in-time provisioning
Without SCIM, create or update the user on first SSO sign-in from the assertion's attributes. Key the link on (connection, NameID or sub), never on email alone.
Common mistakes
- Letting tenants claim email domains without DNS verification.
- Reading attributes from an unsigned part of the SAML response.
- Leaving sessions alive after SCIM deactivation.
- One global SAML certificate shared across all customers.
Key takeaways
- Treat SAML XML as hostile input; signature wrapping has broken many libraries, including ruby-saml in 2025.
- Verify domain ownership with DNS before any tenant can route users to its IdP.
- Keep a malicious-response test suite and run it on every library upgrade.
- On SCIM deactivation, revoke every session and refresh token immediately.