SAML for enterprise sign-in
Open in the interactive app: practice, quiz, mock interview →In one minute
- SAML 2.0 is an XML-based standard for single sign-on: an identity provider (IdP) authenticates the user and sends a signed assertion to a service provider (SP), which logs the user in.
- The browser carries messages between IdP and SP through redirects and auto-submitted forms, so the two servers never need to talk directly at login time.
- Trust comes from exchanged metadata: entity ids, endpoint URLs, and the IdP's signing certificate.
- Security depends almost entirely on the SP validating the assertion correctly: signature, audience, recipient, time window, and replay. Most SAML breaches are validation bugs.
- SAML dominates enterprise workforce SSO. New consumer and mobile integrations usually choose OpenID Connect.
How it works
Roles and setup
The IdP (Okta, Entra ID, ADFS, Google Workspace) owns user accounts and authentication, including MFA. The SP is your application. Setup exchanges metadata: the SP gives its entity id and Assertion Consumer Service (ACS) URL; the IdP gives its entity id, SSO URL, and X.509 signing certificate.
SP-initiated flow
- The user visits the app. The SP creates an AuthnRequest with a unique id and redirects the browser to the IdP.
- The IdP authenticates the user, or reuses its own session.
- The IdP builds a Response containing an Assertion: subject (NameID), attributes (email, groups), conditions (NotBefore, NotOnOrAfter, Audience), and InResponseTo set to the request id. It signs the assertion, the response, or both.
- The browser POSTs the Response to the ACS URL via an auto-submitting HTML form.
- The SP validates it and creates its own session.
IdP-initiated flow skips step 1: the user clicks the app tile in the IdP portal. With no request id to match, it is more exposed to injection and replay, so many SPs restrict or disable it.
Validation checklist
- Verify the XML signature with the configured IdP certificate, never a certificate embedded in the message. Require RSA-SHA256 or stronger and reject SHA-1 signature and digest algorithms (OWASP SAML cheat sheet).
- Make sure the signed element is the one you read. XML signature wrapping attacks add an unsigned assertion alongside a signed one and rely on the SP reading the wrong one. Schema-validate first and select elements with absolute paths, never "find the first Assertion anywhere".
- Check Issuer equals the expected IdP, Audience equals your entity id, and Recipient and the Response's Destination equal your ACS URL.
- Enforce NotBefore and NotOnOrAfter with a small clock skew, for example 2 minutes.
- Match InResponseTo to an outstanding request, and record assertion ids until they expire to block replay. NIST's federation guideline makes audience restriction and replay protection mandatory at every assurance level (NIST SP 800-63C-4).
- Use a maintained library with safe XML parsing, and patch it quickly: signature-bypass bugs in widely used SAML libraries turned up in 2012, 2018, 2024 and 2025 (see In the wild).
Provisioning and logout
SAML covers login only. Accounts come from SCIM provisioning or just-in-time creation. Single logout is fragile, so bound SP sessions independently.
Down the stack
Layer 1The contract
The SP's contract is narrow: log a user in only from an assertion that is signed by the configured IdP key, addressed to this SP (Audience) and this endpoint (Recipient), currently within its validity window, never used before, and, for SP-initiated logins, answering a request this SP actually sent. The IdP's side of the contract is that it authenticated the subject at AuthnInstant using the method named in AuthnContextClassRef, such as password plus MFA. SAML says nothing about how long the SP's own session lasts. A bearer assertion is like cash: whoever holds it can present it, which is why NIST allows bearer assertions only up to its second federation level and requires holder-of-key or a bound authenticator at the top level (NIST SP 800-63C-4).
Layer 2The mechanism
The AuthnRequest usually travels with the HTTP-Redirect binding: the XML is compressed with raw DEFLATE (RFC 1951), base64-encoded, URL-encoded into a SAMLRequest parameter, and optionally signed with SigAlg and Signature query parameters. The Response comes back with the HTTP-POST binding as a base64 SAMLResponse form field plus RelayState. The signature is an enveloped XML-DSig ds:Signature element. Its Reference URI="#_abc" points at the signed element's ID, its transforms are enveloped-signature and exclusive canonicalisation, its DigestValue is a SHA-256 of the canonicalised element, and its SignatureValue signs the canonicalised SignedInfo. A SubjectConfirmation with method bearer carries Recipient, NotOnOrAfter, and InResponseTo. Signature wrapping works because the verifier resolves the signed element by ID while the application finds the assertion by a different path, such as the first Assertion element in the document. Somorovsky and colleagues found this gap exploitable in 11 of 14 major SAML frameworks in 2012 (USENIX Security 2012). A subtler variant is a parser differential: canonicalisation drops XML comments, so alice@corp.com<!---->.evil.com is signed as alice@corp.com.evil.com, but a library that reads only the first text node sees alice@corp.com (CERT VU#475445). The fix in every case is the same: read identity only from the exact bytes the signature covered.
Layer 3The machine
A signed response is typically 5 to 15 KB of XML, a third larger once base64-encoded into the POST body. Redirect-binding URLs must stay under server limits, often 8 KB, which is why requests are deflated. Canonicalisation builds a DOM, resolves namespaces, and reorders attributes, so it costs far more CPU and allocation than the RSA verification itself, which takes around 30 microseconds for a 2048-bit key with public exponent 65537. XML parsers are an attack surface: nested entity definitions ten levels deep with ten references each expand to a billion entities and exhaust memory, and external entities can read local files, so DTD processing must be disabled. The ACS POST arrives cross-site from the IdP's domain, so a pre-login cookie set with SameSite=Lax is not sent with it; SPs correlate the response through RelayState or a cookie marked SameSite=None; Secure. RelayState must not exceed 80 bytes (SAML 2.0 Bindings), so store an opaque key that maps to the return URL server-side rather than the URL itself, which also avoids an open redirect.
Why it's built this way
Enterprise IdPs often sit behind firewalls the SaaS cannot reach, so the browser carries every message. XML was the enterprise standard when SAML 2.0 became an OASIS Standard in March 2005 (OASIS technical overview), and XML has many equivalent byte representations, so signatures need canonicalisation. Bearer assertions can be intercepted, so they are short-lived and single-use. Signing parts of a document allows flexible processing but creates the gap that wrapping attacks exploit.
Diagram
sequenceDiagram participant B as Browser participant SP as App (SP) participant IdP B->>SP: GET /dashboard SP-->>B: redirect with AuthnRequest (id=r1) B->>IdP: AuthnRequest IdP->>B: login + MFA if no session IdP-->>B: HTML form with signed Response B->>SP: POST /acs (SAMLResponse) SP->>SP: verify signature, audience, time, InResponseTo=r1, replay SP-->>B: session cookie, redirect to /dashboard
Worked example
A B2B SaaS sells to 1,500 enterprise customers, each with its own IdP. Peak SSO logins are 300 per second at 9 a.m. across time zones.
Per-tenant configuration: each customer has an IdP entity id, SSO URL, and one or two signing certificates. 1,500 tenants x 2 certificates is 3,000 certificates in a small table, cached in memory.
Validation cost: parsing a 10 KB response and verifying an RSA-2048 signature takes 1 to 2 ms of CPU, under one core at 300 logins per second.
Replay cache: assertion ids are kept until their NotOnOrAfter, typically 5 minutes. 300 per second x 300 seconds = 90,000 entries, a few MB in a shared store such as Redis with TTLs. It must be shared across SP instances, or an attacker replays to a different instance.
Certificate expiry: with 1,500 IdPs rotating certificates every 1 to 3 years, 2 to 4 rotations happen per working day. Track each expiry, notify admins 30 days ahead, accept a second certificate during rollover, and poll IdP metadata URLs where available. Entra ID, for example, issues SAML signing certificates valid for three years by default, emails admins 60, 30 and 7 days before expiry, and asks SaaS vendors to hold a primary and a secondary certificate and re-read each tenant's metadata at least every 24 hours (Microsoft Learn). At 1,500 tenants that is 1,500 metadata fetches a day, trivial next to the login traffic.
In the wild
- CERT/CC and Duo, 2018: XML comments split identities in several SAML libraries. Affected libraries included OneLogin python-saml and ruby-saml, OmniAuth-SAML, Clever saml2-js and Shibboleth OpenSAML C++; they read a node's text in a way that stopped at a comment, while the signature covered the text with comments removed. An attacker who could register
victim@corp.com<!---->.evil.comat the IdP could log in asvictim@corp.com. Vendors shipped patched releases and the note was published on 27 February 2018 (CERT VU#475445). - GitLab and ruby-saml, 2024 and 2025: forged assertions accepted twice in six months. CVE-2024-45409, rated critical, was a SAML authentication bypass in the ruby-saml and omniauth-saml dependencies; GitLab shipped fixes in 17.3.3 and four older branches, and warned that turning on MFA at the identity provider did not mitigate it (GitLab). In March 2025 GitHub Security Lab found that ruby-saml read the signature with REXML and the digest with Nokogiri, two parsers that could be made to see different
Signatureelements; CVE-2025-25291 and 25292 were fixed in ruby-saml 1.18.0 and an exploitable instance was found in GitLab (GitHub Blog). - SolarWinds intrusions, 2020: stolen signing certificate, valid forged tokens. After gaining high Active Directory privileges, the attackers took the organisation's SAML token-signing certificate and minted tokens that cloud email and file services accepted as genuine, so every SP check passed. CISA told defenders to look for "impossible tokens" (no matching sign-in within about an hour, missing MFA claims, unusual lifetimes) and, once SAML abuse is found, to treat the whole identity trust store as compromised (CISA AA20-352A).
Trade-offs
| Option | Strengths | Weaknesses | Choose when |
|---|---|---|---|
| SAML 2.0 | Universal enterprise IdP support, mature | XML signature complexity, browser-only flows | Enterprise workforce SSO |
| OpenID Connect | JSON and JWT, works for mobile and APIs, simpler | Some legacy enterprise IdPs lack it | New apps, consumer login, mobile |
| SSO broker service | One integration, many IdPs handled for you | Vendor dependency, cost per connection | Many enterprise customers, small team |
| Build on a SAML library in-house | Full control, no per-connection fees | You own every validation bug and support ticket | Strong security team, unusual needs |
Pitfalls in production
- XML signature wrapping: validating one element and reading another. Use a library that returns only the verified assertion, and read attributes from that.
- Trusting the certificate inside the message. Pin the IdP certificate from metadata per tenant.
- No replay protection across instances. Store assertion ids in a shared cache until they expire.
- IdP certificate rotation breaks logins for a customer overnight. Support two certificates, monitor expiry, and consume metadata URLs.
- Matching users on a mutable attribute such as email lets an IdP admin take over accounts by changing addresses. Bind accounts to a stable NameID per tenant.
- Treating the SP as the only thing to secure. Whoever holds the IdP's signing key can mint assertions every SP accepts. Keep that key in an HSM or managed IdP, alert on federation trust changes, and correlate SP logins with IdP sign-in logs.
Leadership lens
- Decide build versus buy early; per-tenant SSO support is an ongoing operational cost, not a one-time feature.
- Ask how deprovisioning works. Without SCIM, removed employees keep sessions and accounts.
- Offer OIDC alongside SAML for new integrations, and keep SP session lifetime bounded independently of the IdP.
Check yourself
Why must the SP check that InResponseTo matches a request it actually sent?
Show answer
It ties the response to a login this browser started, which blocks unsolicited assertions and some replay and login-CSRF attacks.
How does an XML signature wrapping attack work?
Show answer
The attacker keeps a validly signed assertion in the document and adds a forged unsigned one. If the SP verifies the signature on one element but reads identity from another, the forged identity is accepted.
Why is the Audience check necessary even with a valid signature?
Show answer
The IdP signs assertions for many SPs. Without the audience check, an assertion issued for another app could log the user into yours.
Why should account linking use a stable NameID instead of email?
Show answer
Emails can be reassigned or edited by IdP admins, letting one person's assertion map to another person's account.
Sources and further study
Primary
- OASIS, Assertions and Protocols for SAML 2.0 (core spec): the normative definition of Assertion, Conditions, SubjectConfirmation and the processing rules.
- OASIS, Bindings for SAML 2.0: exactly how messages ride HTTP-Redirect (DEFLATE) and HTTP-POST, including the RelayState limit.
- Somorovsky et al., On Breaking SAML (USENIX Security 2012): the systematic study of signature wrapping across real frameworks.
- NIST SP 800-63C-4, Federation and Assertions: federation assurance levels, bearer versus holder-of-key, and mandatory audience and replay checks.
Systems docs
- Microsoft Entra ID: single sign-on SAML protocol: what one major IdP actually puts in AuthnRequest and Response.
- GitHub Security Lab: Sign in as anyone: a step-by-step walkthrough of a 2025 parser-differential bypass.
Books
- Building Secure and Reliable Systems, Adkins et al., chapter 5 "Design for Least Privilege": authentication and authorization decisions as a policy framework, which is the frame for federated login. Free online.
- Building Microservices (2nd edition), Sam Newman, chapter 11 "Security": implicit trust versus zero trust and how identity flows between services after the SSO login.
Other curricula
- roadmap.sh backend roadmap: lists SAML as one node among the authentication methods, next to OAuth, OpenID and JWT, without the validation details.
- donnemartin/system-design-primer: its security section is four bullets and does not cover federation or SSO at all.
Watch
- A Developer's Guide to SAML (OktaDev): the flows and message structure from the implementer's side.
- What Is Single Sign-on (SSO)? How It Works (ByteByteGo): SAML and OIDC side by side.
Free resources
- SAML 2.0 Technical Overview (OASIS): the standards body's own explanation of profiles, bindings, and assertions.
- OWASP SAML Security Cheat Sheet: validation rules and known attacks, including signature wrapping.
- Fun with SAML SSO vulnerabilities and footguns (WorkOS): real-world implementation bugs and how they were exploited.
- Understanding SAML (Okta Developer): a vendor-neutral overview of SP and IdP roles and flows.