How SAML Works: Enterprise Single Sign-On and Federation
Security Assertion Markup Language (SAML) is an XML-based open standard for exchanging authentication and authorization data between parties. In practice, SAML is the protocol that powers enterprise single sign-on (SSO): when you click "Sign in with your company account" on a SaaS application and get redirected to your corporate login page, SAML is almost certainly the protocol handling that exchange behind the scenes. Defined by OASIS, SAML 2.0 (2005) remains the dominant federation protocol in enterprise environments, even as newer alternatives like OpenID Connect have gained ground in consumer-facing applications.
The Problem SAML Solves
Before federated identity, every application maintained its own user database. An employee at a company with 50 SaaS applications would have 50 separate accounts with 50 separate passwords. This creates several serious problems:
- Password fatigue — Users reuse passwords across services, meaning a breach of one application compromises others.
- Provisioning overhead — IT administrators must create and delete accounts individually in every application when employees join, change roles, or leave.
- No centralized policy — Multi-factor authentication, password complexity requirements, and session policies must be configured separately in each application.
- Audit gaps — There is no single place to see which applications a user has accessed or to revoke all access at once.
SAML solves this by federating identity: one authoritative system (the Identity Provider) manages user authentication, and all other applications (Service Providers) trust its assertions. The user logs in once and gains access to all federated applications — hence "single sign-on."
SAML Terminology
SAML introduces specific terminology that maps to real-world roles:
- Identity Provider (IdP) — The system that authenticates users and issues identity assertions. Examples: Okta, Azure AD (Entra ID), PingFederate, Shibboleth, ADFS. The IdP maintains the user directory and enforces authentication policies (passwords, MFA, conditional access).
- Service Provider (SP) — The application that relies on the IdP for authentication. Examples: Salesforce, Workday, AWS Console, Jira, Slack. The SP does not manage user credentials — it delegates authentication to the IdP and consumes the resulting assertion.
- Assertion — An XML document issued by the IdP that contains statements about the user. This is the core artifact of the protocol.
- Binding — The mechanism used to transport SAML messages over standard protocols. SAML defines several bindings including HTTP-POST, HTTP-Redirect, and SOAP.
- Metadata — An XML document that describes an IdP or SP's endpoints, certificates, and capabilities. Metadata exchange is how IdPs and SPs establish trust before any authentication can occur.
- RelayState — An opaque string that preserves the user's intended destination through the authentication flow. If you tried to access a specific page, RelayState ensures you end up there after login.
SAML Assertions: The Core Data Structure
A SAML assertion is an XML document containing one or more statements about a subject (the user). There are three types of statements:
- Authentication Statement — Declares that the subject was authenticated by the IdP at a specific time using a specific method (password, MFA, certificate, etc.).
- Attribute Statement — Contains key-value pairs describing the subject: email address, display name, group memberships, roles, department, employee ID — whatever attributes the SP needs.
- Authorization Decision Statement — States whether the subject is permitted or denied access to a specified resource. This is rarely used in practice; most authorization decisions are made by the SP based on attributes.
A simplified SAML assertion looks like this:
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_abc123" IssueInstant="2025-01-15T14:30:00Z" Version="2.0">
<saml:Issuer>https://idp.example.com</saml:Issuer>
<ds:Signature>...</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
[email protected]
</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData
Recipient="https://app.example.com/saml/acs"
NotOnOrAfter="2025-01-15T14:35:00Z"
InResponseTo="_req456"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2025-01-15T14:29:00Z" NotOnOrAfter="2025-01-15T14:35:00Z">
<saml:AudienceRestriction>
<saml:Audience>https://app.example.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2025-01-15T14:30:00Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="email">
<saml:AttributeValue>[email protected]</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="groups">
<saml:AttributeValue>engineering</saml:AttributeValue>
<saml:AttributeValue>admin</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
Critical fields include: the Issuer (identifies the IdP), the Subject (identifies the user), the Conditions (restrict the assertion's validity window and intended audience), and the XML digital signature that proves the assertion was issued by the IdP and has not been tampered with.
SP-Initiated SSO Flow
The most common SAML flow is SP-initiated SSO, where the user starts at the Service Provider. This is what happens when you visit a SaaS application and it redirects you to your company's login page.
Here is the step-by-step breakdown:
- User accesses the SP — The user navigates to the application (e.g.,
https://app.example.com/dashboard). The SP detects there is no active session. - SP generates AuthnRequest — The SP creates a SAML AuthnRequest XML document specifying its entity ID, the desired assertion consumer service (ACS) URL, and a request ID. It redirects the user's browser to the IdP's SSO endpoint with this request encoded in the query string (HTTP-Redirect binding) or as a hidden form field (HTTP-POST binding).
- Browser contacts the IdP — The user's browser follows the redirect to the IdP. The AuthnRequest tells the IdP which SP is requesting authentication and where to send the response.
- IdP authenticates the user — If the user does not already have a session at the IdP, the IdP presents a login form. The user enters their credentials and completes any required MFA challenges. If the user already has an active IdP session, this step is skipped — this is what makes SSO seamless.
- IdP generates SAMLResponse — After successful authentication, the IdP constructs a SAMLResponse containing a signed assertion with the user's identity and attributes. The IdP returns an HTML page containing an auto-submitting form with the SAMLResponse as a hidden field.
- Browser POSTs to the SP's ACS — The auto-submitting form sends the SAMLResponse to the SP's Assertion Consumer Service URL via HTTP POST.
- SP validates the assertion — The SP verifies the XML signature against the IdP's known certificate, checks that the assertion is not expired, confirms the audience restriction matches its own entity ID, and validates the
InResponseTofield matches the original request ID. - SP creates a session — If validation passes, the SP creates a local session for the user, sets a session cookie, and redirects to the originally requested resource.
IdP-Initiated SSO Flow
In IdP-initiated SSO, the user starts at the Identity Provider — typically a portal page listing all available applications. The user clicks on an application icon, and the IdP sends a SAMLResponse directly to the SP without a preceding AuthnRequest.
This flow is simpler but less secure. Because there is no AuthnRequest, there is no request ID for the SP to validate in the InResponseTo field, which means the SP cannot tie the response to a specific request. This opens the door to replay attacks where an attacker captures a SAMLResponse and submits it later. To mitigate this, SPs must carefully enforce assertion validity windows and track consumed assertion IDs.
IdP-initiated SSO is also vulnerable to unsolicited response attacks where an attacker who can generate or obtain a valid assertion for one SP might try to use it at another SP. The AudienceRestriction element in the assertion prevents this if the SP validates it correctly.
SAML Bindings: How Messages Travel
SAML is transport-agnostic — the specification defines "bindings" that map SAML messages onto standard transport protocols. The two most common bindings are:
HTTP-Redirect Binding
The SAML message is deflated (compressed), Base64-encoded, URL-encoded, and sent as a query parameter in an HTTP 302 redirect. This is typically used for AuthnRequests because they are small. The URL looks like:
https://idp.example.com/sso?SAMLRequest=fZJNT8MwDI...&RelayState=%2Fdashboard&SigAlg=...&Signature=...
There is a practical limitation: URLs have length limits (around 2048 characters in some browsers and servers), so this binding is unsuitable for large messages like assertions with many attributes.
HTTP-POST Binding
The SAML message is Base64-encoded and embedded as a hidden field in an HTML form that auto-submits via JavaScript. This is the standard binding for SAMLResponses because assertions can be large. The IdP returns an HTML page like:
<form method="POST" action="https://app.example.com/saml/acs"> <input type="hidden" name="SAMLResponse" value="PHNhbWxwOl..." /> <input type="hidden" name="RelayState" value="/dashboard" /> <noscript><input type="submit" value="Continue" /></noscript> </form> <script>document.forms[0].submit();</script>
The <noscript> fallback ensures the flow works even without JavaScript — the user just has to click a button.
Other Bindings
SAML also defines an Artifact binding where only a short reference (artifact) is passed through the browser, and the SP contacts the IdP directly via a back-channel SOAP call to resolve the full assertion. This is useful when assertion size is a concern or when you want to avoid exposing the assertion to the user's browser. SOAP binding, Reverse SOAP (PAOS), and URI binding also exist but are rarely used in modern deployments.
XML Signature and Security
SAML assertions are digitally signed using XML Signature (XMLDSig) to ensure integrity and authenticity. The IdP signs the assertion (or the entire response) using its private key, and the SP verifies the signature using the IdP's public key obtained from metadata exchange.
XML signatures in SAML can appear at two levels:
- Response-level signature — The entire
<samlp:Response>element is signed. This proves the response came from the IdP. - Assertion-level signature — The individual
<saml:Assertion>element is signed. This proves the assertion itself is authentic, regardless of the containing response.
Best practice is to sign at the assertion level (or both), because if only the response is signed, an attacker who can inject content into the response outside the assertion could tamper with it without invalidating the signature.
XML Signature Wrapping Attacks
The most notorious class of SAML vulnerabilities is XML Signature Wrapping (XSW). These attacks exploit the disconnect between which XML elements are covered by the signature and which elements the application logic processes.
The attack works like this: the signature covers a specific XML element identified by a Reference URI attribute. The attacker takes a legitimately signed assertion and moves it to a different location in the XML tree, then inserts a forged assertion where the application expects to find it. The signature still validates (it covers the original assertion, which is still present in the document), but the application processes the forged assertion.
There are several variants of XSW attacks, numbered XSW1 through XSW8 in security research, each exploiting different aspects of how XML parsers and signature validators traverse the document. Defenses include:
- Strict schema validation — Reject any SAML response that does not conform exactly to the expected schema. Extra elements or assertions should cause immediate rejection.
- Explicitly binding signature to assertion — After validating the signature, ensure the signed element is the same element you are extracting identity information from, not just any element with the right ID.
- Canonicalization — Use exclusive XML canonicalization (exc-c14n) to normalize the signed content, reducing the attack surface for XML manipulation.
- Using well-tested libraries — Never implement SAML signature validation from scratch. Use battle-tested libraries that have been patched against known XSW variants.
Metadata Exchange
Before an IdP and SP can exchange SAML messages, they must exchange metadata — XML documents that describe each party's endpoints, certificates, and capabilities. This is how trust is bootstrapped.
SP metadata typically includes:
- Entity ID — A globally unique identifier for the SP, usually a URL like
https://app.example.com/saml/metadata. - Assertion Consumer Service (ACS) URL — Where the IdP should POST the SAMLResponse.
- Single Logout Service URL — Where logout requests should be sent.
- Signing/encryption certificate — The SP's public key for verifying SP-signed requests or encrypting assertions.
- NameID format — The identifier format the SP expects (email, persistent, transient, etc.).
IdP metadata typically includes:
- Entity ID — The IdP's unique identifier.
- SSO Service URL — The endpoint that accepts AuthnRequests (with the binding type: POST or Redirect).
- Single Logout Service URL — The endpoint for logout requests.
- Signing certificate — The public key SPs use to verify assertion signatures.
Metadata can be exchanged manually (download XML file, upload to the other party) or dynamically via well-known URLs. Many IdPs publish their metadata at a URL like https://idp.example.com/saml/metadata. Dynamic metadata exchange reduces configuration errors but introduces a new trust dependency: the metadata URL must be served over TLS and the SP must verify the certificate to prevent metadata injection attacks.
SAML vs. OpenID Connect
SAML and OpenID Connect (OIDC) solve similar problems — federated single sign-on — but take fundamentally different approaches:
| Aspect | SAML 2.0 | OpenID Connect |
|---|---|---|
| Data format | XML | JSON (JWT) |
| Transport | HTTP Redirect/POST, SOAP | REST/HTTP |
| Built on | XML Schema, XMLDSig, XML Encryption | OAuth 2.0, JWT, JOSE |
| Primary use | Enterprise SSO | Consumer + enterprise SSO |
| Mobile support | Poor (XML is heavy) | Excellent (JSON is lightweight) |
| Specification age | 2005 | 2014 |
| Discovery | Metadata XML | .well-known/openid-configuration |
SAML remains dominant in enterprises with existing IdP infrastructure (especially ADFS, PingFederate, and Shibboleth), regulated industries that have invested heavily in SAML-based compliance tooling, and B2B SaaS where customers demand SAML support. New applications increasingly support both protocols, and OIDC is generally preferred for greenfield development due to its simplicity and better mobile support.
Single Logout
SAML defines a Single Logout (SLO) mechanism that allows a user to log out of all SPs simultaneously by initiating logout at any one SP or at the IdP. The logout process sends LogoutRequest messages to all SPs that have active sessions for the user.
In practice, SLO is fragile and often partially implemented. Problems include:
- Browser limitations — The logout flow must visit each SP via the user's browser (front-channel), and if any SP is slow or unreachable, the chain breaks.
- Iframe restrictions — Some implementations use hidden iframes to contact SPs, but browsers increasingly block cross-site requests in iframes.
- Session mismatch — SPs may have their own session timeouts that are shorter than the IdP session, leading to inconsistent state.
- Back-channel logout — Some implementations use server-to-server (back-channel) logout requests, which are more reliable but require the IdP to maintain a list of active sessions per SP.
Many organizations address this by setting short session timeouts on SPs and relying on the IdP session as the primary control point, rather than implementing full SLO.
Assertion Encryption
While SAML assertions are always transmitted over TLS, the assertion passes through the user's browser (in the HTTP-POST binding). A sophisticated attacker who has compromised the browser or intercepted the TLS connection could read the assertion contents. SAML supports assertion encryption using XML Encryption, where the IdP encrypts the assertion with the SP's public key from its metadata.
Encrypted assertions look like this in the response:
<saml:EncryptedAssertion>
<xenc:EncryptedData>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<ds:KeyInfo>
<xenc:EncryptedKey>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
<xenc:CipherData><xenc:CipherValue>...</xenc:CipherValue></xenc:CipherData>
</xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData><xenc:CipherValue>...</xenc:CipherValue></xenc:CipherData>
</xenc:EncryptedData>
</saml:EncryptedAssertion>
The SP decrypts the assertion using its private key, then validates the signature on the contained assertion as usual. While encryption adds defense in depth, it also adds complexity — key management, certificate rotation, and ensuring the SP can handle encrypted assertions all require careful implementation.
NameID Formats
The NameID element in a SAML assertion identifies the subject (user). SAML defines several formats:
- emailAddress — The user's email address. Simple and human-readable, but ties identity to a potentially changing attribute. Format URI:
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress - persistent — An opaque, permanent identifier unique to the user-SP pair. The same user gets different persistent IDs at different SPs, preventing SPs from correlating users. Format URI:
urn:oasis:names:tc:SAML:2.0:nameid-format:persistent - transient — A temporary identifier that changes with each session. Used when the SP does not need to track the user across sessions. Format URI:
urn:oasis:names:tc:SAML:2.0:nameid-format:transient - unspecified — No specific format is required. The IdP can send whatever identifier it chooses.
The choice of NameID format has privacy implications. Persistent and transient formats protect user privacy by preventing SPs from correlating identities, while email-based NameIDs make correlation trivial.
Real-World SAML Configuration
Setting up a SAML integration between an IdP and SP typically involves these steps:
- Exchange metadata — The SP administrator downloads the IdP's metadata XML (or enters the IdP's metadata URL). The IdP administrator downloads the SP's metadata XML or manually enters the SP's entity ID and ACS URL.
- Configure attribute mapping — Define which IdP attributes map to which SP fields. For example, the IdP might send
mailas the email attribute, but the SP expectsemail. This attribute mapping is a common source of SSO configuration errors. - Configure NameID — Agree on the NameID format and which IdP attribute to use as the NameID value.
- Test the integration — Perform an SP-initiated login flow and verify that the assertion contains the expected attributes with correct values.
- Certificate rotation planning — SAML signing certificates eventually expire. Plan for certificate rotation: the IdP publishes a new certificate in its metadata before the old one expires, and SPs must update their trusted certificates. This is a frequent source of outages when not planned properly.
Security Considerations
Beyond XML Signature Wrapping attacks, SAML implementations must defend against several other threats:
- Replay attacks — An attacker captures a valid SAMLResponse and replays it. Defense: enforce
NotOnOrAfterconditions and maintain a cache of consumed assertion IDs to reject duplicates. - Recipient mismatch — An assertion intended for one SP is used at another. Defense: validate the
Recipientattribute inSubjectConfirmationDatamatches the current SP's ACS URL. - Audience mismatch — Defense: validate the
AudienceRestrictionelement contains the current SP's entity ID. - Clock skew — IdP and SP clocks are out of sync, causing valid assertions to be rejected or expired assertions to be accepted. Defense: allow a small clock skew tolerance (typically 30-60 seconds) but no more.
- Open redirect in RelayState — An attacker crafts a login URL with a malicious RelayState that redirects the user to a phishing site after successful authentication. Defense: validate that RelayState URLs are relative or belong to expected domains.
- XML External Entity (XXE) attacks — Malicious DTD declarations in SAML XML can read local files on the SP. Defense: disable DTD processing and external entity resolution in the XML parser.
SAML in the Network Stack
SAML operates at the application layer but depends on the entire network stack for secure operation:
- DNS resolves IdP and SP endpoints. DNS hijacking could redirect SAML flows to malicious servers, though TLS certificate validation would prevent the attack from succeeding silently.
- TLS encrypts all SAML messages in transit. Without TLS, the entire protocol is insecure — assertions could be intercepted and replayed despite XML signatures.
- BGP routes traffic between users, SPs, and IdPs. A BGP hijack affecting an IdP's network could disrupt authentication for all federated SPs.
- OAuth 2.0 / OIDC are the modern alternatives. Many IdPs now support both SAML and OIDC, allowing organizations to choose the best protocol for each use case.
Relevant RFCs and Standards
- SAML 2.0 Core — OASIS Standard, March 2005: defines assertions, protocols, and bindings.
- SAML 2.0 Profiles — OASIS Standard: defines SSO profiles including Web Browser SSO and Single Logout.
- SAML 2.0 Bindings — OASIS Standard: defines HTTP-POST, HTTP-Redirect, SOAP, and other transport bindings.
- SAML 2.0 Metadata — OASIS Standard: defines the metadata XML schema for IdP and SP discovery.
- XML Signature (XMLDSig) — W3C Recommendation: the foundation for SAML assertion integrity.
See It in Action
Major SAML Identity Providers operate on networks routed via BGP. You can explore their infrastructure using the god.ad BGP Looking Glass:
- AS8075 — Microsoft (Azure AD / Entra ID, ADFS)
- AS13335 — Cloudflare (Cloudflare Access with SAML)
- AS14618 — Amazon (AWS SSO / IAM Identity Center)
- AS15169 — Google (Google Workspace SAML)
- login.microsoftonline.com — Resolve Microsoft's SAML/OIDC endpoint