SAML 2.0: the standard that invented web single sign-on

How SAML 2.0 federates identity into web apps: the IdP, SP, and user roles and trust through metadata XML, SP-initiated and IdP-initiated flows, the Redirect, POST, and Artifact bindings, the anatomy of a SAML assertion, signing and encryption, and when SAML is still the right choice over OAuth and OIDC.

A note you can trust

Sara starts her day by opening the company’s expense application, a SaaS product running on someone else’s servers. She doesn’t type a password into it. Her browser bounces briefly to the company sign-in page, which already knows her from earlier that morning, and comes back with her logged in. The expense application never saw her password and never asked her directory anything. It received a note.


That note is a SAML assertion, and SAML is about how it’s written, carried, and checked. The directory services article established where identities live; this one starts moving them. SAML 2.0 is the first protocol in the stack, the one that took an identity sitting in a corporate directory and made it usable for signing in to applications the directory doesn’t own. It’s an OASIS standard finalized in 2005, and two decades later it still handles sign-in for a staggering share of enterprise software.


The problem it solved is one every employee feels. You have one corporate identity and dozens of applications, many of them SaaS. Without federation, each needs its own password, which is bad for security and worse for patience. SAML’s answer is to let one trusted system authenticate you and let every application trust that system’s word instead of running its own sign-in. The word is a signed XML document, the assertion: in effect a tamper-proof note saying “this is Sara, she authenticated, here are her details.” The application doesn’t check Sara’s password; it checks the signature and trusts the note. Everything else is the format of the note and how it’s delivered.


Three roles, and the trust between them

SAML has three actors, and keeping them straight makes the rest easy.


The identity provider (IdP) authenticates the user and issues assertions. It’s backed by the directory: Entra ID, Okta, ADFS, Ping. The IdP is where the password, or the MFA, is actually checked. The service provider (SP) is the application the user wants to reach. It hands authentication to the IdP and consumes the assertion; Sara’s expense tool is an SP. And the principal is the user, who experiences all of this as “click the app, you’re in.”


Trust is set up with metadata

An SP can’t trust any assertion that happens to arrive. It needs to know in advance, and cryptographically, which IdP to trust and how to check its signatures. That’s set up through SAML metadata, an XML document each party publishes about itself. It contains the party’s entityID, its unique identifier, usually a URL; its endpoints, where to send and receive SAML messages, such as the SP’s Assertion Consumer Service URL; its signing certificates, the public keys the other side uses to verify signatures; and the bindings and NameID formats it supports.


Setting up a SAML integration is, at bottom, exchanging metadata. The IdP and the SP import each other’s metadata, and from then on each knows the other’s identity, endpoints, and public keys. That trust, set up ahead of time and anchored in certificates, is why an SP can believe an assertion without ever contacting the user’s directory.


sequenceDiagram
  accTitle: Establishing SAML trust through metadata exchange
  accDescr: Before any sign-in, the identity provider and service provider exchange metadata XML. The IdP shares its metadata with its entityID, sign-in endpoint, and signing certificate. The SP shares its metadata with its entityID, Assertion Consumer Service URL, and certificate. Each imports the other's metadata, and from then on they trust each other, so single sign-on can happen.
  participant SP as Service provider
  participant IdP as Identity provider
  IdP->>SP: IdP metadata (entityID, SSO URL, signing cert)
  SP->>IdP: SP metadata (entityID, ACS URL, cert)
  Note over SP,IdP: Each imports the other's metadata, and SSO can start
Trust is built once, before any sign-in: each side imports the other's metadata, and from then on the SP can verify the IdP's signatures and the IdP knows where to send assertions.

Trust set up once isn’t trust maintained forever. The signing certificate in an IdP’s metadata has an expiry date. When it expires or is rotated and the SP keeps the old copy, signature checks fail and every user is locked out of that application. It’s one of the most common SAML outages in production, and the fix is boring: automate metadata refresh, or at least put the certificate’s expiry date in a calendar someone watches.


Two ways to start: SP-initiated and IdP-initiated

A single sign-on session can begin in two ways, and the difference matters for both convenience and security.


SP-initiated

The user starts at the application. This is the common, recommended flow, and it’s what happened when Sara opened the expense tool.


sequenceDiagram
  accTitle: SP-initiated SAML single sign-on
  accDescr: The user requests a protected page at the service provider. The SP creates an authentication request and redirects the user's browser to the identity provider. The IdP authenticates the user with password and MFA, builds a signed SAML assertion, and posts it back through the browser to the SP's Assertion Consumer Service. The SP checks the signature and conditions, creates a session, and grants access.
  actor U as User (browser)
  participant SP as Service provider (app)
  participant IdP as Identity provider
  U->>SP: Request protected page
  SP->>U: Redirect with AuthnRequest
  U->>IdP: Deliver AuthnRequest
  IdP->>U: Authenticate (password + MFA)
  IdP->>U: Signed assertion (HTTP-POST)
  U->>SP: POST assertion to ACS
  SP->>SP: Check signature and conditions
  SP->>U: Session created, access granted
SP-initiated SSO: the user lands on the app, is sent to the IdP to authenticate, and comes back with a signed assertion the app checks. The app never sees the password.

The SP issues an AuthnRequest and redirects the browser to the IdP. The IdP authenticates the user, builds a signed assertion, and sends the browser back to the SP’s Assertion Consumer Service (ACS) URL carrying it. The SP checks the assertion and creates its own session. Two things are worth noticing. The assertion travels through the user’s browser, because SAML is a browser-mediated, front-channel protocol. And the SP matches the response to the request it started, which shuts out whole classes of injection attacks.


IdP-initiated

Here the user starts at the IdP, usually a portal of application tiles, and clicks one. The IdP sends an unsolicited assertion straight to the SP’s ACS, with no AuthnRequest before it. It’s convenient, the classic launchpad experience, but weaker. With no request to match against, an assertion captured in transit is easier to replay, and the SP has less context to check. Current guidance is to prefer SP-initiated for anything sensitive and to enable IdP-initiated deliberately, as a convenience, rather than by default.


Bindings: how SAML messages travel

A binding is the transport, how a SAML message is carried over HTTP. SAML 2.0 defines three you’ll meet.


BindingHow it worksTypical use
HTTP-RedirectThe message is compressed and placed in the URL’s query stringSending the short AuthnRequest from SP to IdP
HTTP-POSTThe message is base64-encoded in a hidden form field that the browser submits automaticallyReturning the assertion from IdP to SP, since assertions are too large for a URL
HTTP-ArtifactThe browser carries only a small reference, and the SP fetches the real assertion over a back channelHigh-assurance setups that keep the assertion off the front channel

The pattern in nearly every deployment is Redirect for the request and POST for the assertion. The AuthnRequest is small enough for a URL; the assertion, full of signed XML, isn’t, so it comes back as a form that submits itself. Artifact is rarer but useful when you don’t want the assertion passing through the browser at all. The browser carries a one-time handle, and the SP exchanges it directly with the IdP, keeping the sensitive content on a server-to-server channel.


Anatomy of an assertion

The assertion is the heart of SAML. It’s an XML document with four parts you should be able to recognize on sight.


<saml:Assertion ID="_a1b2c3" IssueInstant="2026-06-10T09:00:00Z">
  <saml:Issuer>https://idp.example.com</saml:Issuer>
  <ds:Signature>...</ds:Signature>
 
  <saml:Subject>
    <saml:NameID Format="...emailAddress">sara@example.com</saml:NameID>
    <saml:SubjectConfirmation Method="...bearer">
      <saml:SubjectConfirmationData
        Recipient="https://sp.example.com/acs"
        NotOnOrAfter="2026-06-10T09:05:00Z"/>
    </saml:SubjectConfirmation>
  </saml:Subject>
 
  <saml:Conditions NotBefore="2026-06-10T08:59:00Z"
                   NotOnOrAfter="2026-06-10T09:05:00Z">
    <saml:AudienceRestriction>
      <saml:Audience>https://sp.example.com</saml:Audience>
    </saml:AudienceRestriction>
  </saml:Conditions>
 
  <saml:AuthnStatement AuthnInstant="2026-06-10T09:00:00Z"
                       SessionIndex="_sess789">
    <saml:AuthnContext>
      <saml:AuthnContextClassRef>...PasswordProtectedTransport</saml:AuthnContextClassRef>
    </saml:AuthnContext>
  </saml:AuthnStatement>
 
  <saml:AttributeStatement>
    <saml:Attribute Name="department">
      <saml:AttributeValue>Engineering</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>
</saml:Assertion>

Each block answers a different question. The Subject says who the assertion is about: the NameID is the identifier, here an email address, and SubjectConfirmation says how the SP can confirm the subject is the one presenting it, with a Recipient and a NotOnOrAfter that tie it to this SP and this moment. The Conditions say when and for whom it’s valid: NotBefore and NotOnOrAfter set a short window, usually minutes, and AudienceRestriction names the exact SP it’s meant for, so any other SP must reject it. The AuthnStatement says how the user authenticated: AuthnInstant is when, AuthnContextClassRef describes the method, such as a password over TLS or an MFA context, and SessionIndex links to the IdP’s session, which matters later for logout. And the AttributeStatement says what else the SP should know: department, groups, roles, taken from the directory and used by the SP to decide what the user can do.


One structural detail is worth understanding well. The assertion usually travels inside a <samlp:Response> envelope, and the response, the assertion, or both can be signed. That sounds pedantic, but it’s where SAML security is won or lost. An SP that checks only the response’s signature while reading attributes from the assertion has left exactly the gap that XML Signature Wrapping attacks exploit. The rule that prevents it is easy to state and easy to get wrong: verify the signature on the element you actually use, and make sure that signed element is the one whose contents you trust.


An SP’s security rests entirely on checking the assertion, not just reading it. At a minimum it has to verify the XML signature against the IdP’s known certificate, check NotBefore and NotOnOrAfter with very little clock tolerance, confirm the audience is itself, and confirm the recipient matches its ACS URL. An SP that reads attributes before verifying the signature is the classic critical vulnerability: it will believe a forged note.


Signing and encryption

SAML’s trust model is cryptographic, and it splits into two separate concerns.


XML Signature provides integrity and authenticity. The IdP signs the assertion, or the whole response, with its private key, and the SP checks it with the IdP’s public certificate from metadata. A valid signature proves the assertion really came from the trusted IdP and that not a byte changed on the way. In any sensible deployment it’s mandatory; an unsigned assertion is a note anyone could have written.


XML Encryption provides confidentiality. The IdP can encrypt the assertion, or particular attributes, with the SP’s public key, so only the SP can read it. That matters because the assertion passes through the user’s browser, where it can be inspected. If it carries sensitive attributes, a national ID, a salary band, a clinical role, encryption keeps them private. Encryption is optional and used selectively. Signing answers whether you can trust the note; encryption answers who else can read it.


Where SAML implementations go wrong

SAML’s reliance on complex XML has produced a recognizable family of attacks, catalogued in the OWASP SAML Security Cheat Sheet. XML Signature Wrapping restructures the XML so the SP checks a legitimate signature but reads content the attacker controls; the defense is confirming the signature actually covers the element you use. Missing or partial signature checks, accepting assertions without verifying the signature, or verifying the response but not the assertion, is the single most common SAML implementation bug. Audience and recipient confusion, failing to confirm the assertion was issued for your SP, lets an assertion meant for one application be replayed at another. And replay, reusing a captured assertion within its validity window, is limited by short lifetimes and by remembering assertion IDs that have already been used.


The common thread is that SAML is only as secure as the SP’s checking. The protocol is sound; most real-world failures are SPs that check too little.


Single logout: the hard half

SAML also defines Single Logout (SLO), ending a user’s sessions across every federated SP with one action. The SessionIndex in the AuthnStatement makes it possible in principle: it links each SP session to the IdP session, so when the user logs out the IdP can send a LogoutRequest to every SP holding a session under that index.


In practice SLO is notoriously unreliable. Every SP has to implement the logout endpoints correctly, be reachable at that moment, and honor the request, and one misbehaving or offline SP breaks the chain, leaving sessions alive that the user thinks are closed. Many organizations treat SLO as best effort and rely instead on short session lifetimes and revocation at the IdP. The lesson goes well beyond SAML and comes back in the OIDC article: federating sign-in is far easier than federating sign-out. Starting trust in many places at once is simple; ending it everywhere at the same moment, across independent systems, is genuinely hard.


Setting up an integration in practice

What does standing up a SAML connection actually involve? Practitioners follow roughly the same steps.


They exchange metadata, importing the IdP’s into the SP and the SP’s into the IdP, or entering the entityID, ACS URL, and certificates by hand when no metadata URL is offered. They choose the NameID format, deciding what identifies the user uniquely and stably across systems, an email address or a persistent opaque ID; a mismatched NameID is the top cause of “it authenticates, but the app doesn’t recognize the user.” They map attributes, deciding which directory attributes the IdP releases and the exact names the SP expects, which is where most integration time actually goes. They set signing and encryption and confirm both sides agree on algorithms. And they test the edges: first sign-in, signing in again, clock drift between servers, and above all certificate rotation.


The field wisdom is blunt. Most complaints that “SAML is flaky” trace back to attribute mapping mistakes or expired certificates, not to the protocol. Keep the metadata URLs and certificate expiry dates somewhere that’s monitored, prefer signed assertions with tight audience restrictions and short lifetimes, and check rigorously on the SP side. Do that and SAML is boringly reliable; skip it and you’ll be chasing mysterious lockouts every time a certificate rolls over.


When SAML is still the right choice

The next two articles cover OAuth 2.0 and OIDC, which are lighter, based on JSON, and better suited to mobile apps and APIs. That doesn’t make SAML legacy. It makes it specialized, and in its specialty it’s often still the best tool.


For employees signing in to business applications, virtually every enterprise SaaS product supports SAML and every corporate IdP speaks it fluently, so it’s the path of least resistance. For B2B federation, when one company’s employees need access to another company’s systems, SAML’s metadata-based, certificate-anchored trust between two enterprises is mature and well understood. And in regulated sectors with heavy audit requirements, SAML is often deeply embedded, with established controls and assessors who know it; switching protocols carries a risk the regulation doesn’t reward.


SAML is the wrong tool for consumer sign-in at scale, native mobile apps, and authorization between APIs, where XML and browser redirects are clumsy. That’s exactly the territory OAuth 2.0 and OIDC own.


SAML 2.0OAuth 2.0 / OIDC
Data formatXMLJSON and JWT
Built forEnterprise web single sign-onDelegated authorization; consumer and mobile sign-in
TransportBrowser redirects and POSTHTTP and REST, which suits APIs and native apps
Best fitWorkforce and B2B SaaSConsumer, mobile, single-page apps, API access
Enterprise footprintEverywhere, deeply embeddedThe default for anything new

Large organizations usually run both: SAML for the established estate and OIDC for new things. An IAM professional needs to understand the trade-off rather than be loyal to one protocol. A practical rule of thumb: if the user is an employee signing in to a business or B2B web application, SAML is a fine choice, or OIDC if the application supports it equally well. If the user is a consumer, the client is a mobile or single-page app, or you’re authorizing access to an API, reach for OAuth 2.0 and OIDC.


Recap

SAML 2.0 is federated web single sign-on through signed XML assertions.


  1. There are three roles: the IdP authenticates and issues assertions, the SP consumes them, and the user experiences a seamless sign-in. Trust is set up in advance by exchanging metadata with entityIDs, endpoints, and certificates, and it has to be maintained as certificates expire.
  2. There are two flows: SP-initiated, starting at the application and recommended, and IdP-initiated, starting at a portal, convenient but weaker.
  3. There are three bindings: Redirect for the request, POST for the assertion, and Artifact for a back channel in high-assurance setups.
  4. The assertion carries a Subject, Conditions, an AuthnStatement, and an AttributeStatement, and the SP’s security lies entirely in checking all of it, on the element it actually uses.
  5. Signing gives integrity and authenticity and is mandatory; encryption gives confidentiality and is optional. Most SAML breaches are checking failures, not protocol flaws.
  6. Single logout is unreliable in practice, so short sessions and revocation at the IdP do the real work.
  7. SAML still fits workforce single sign-on, B2B federation, and compliance-heavy estates; OAuth and OIDC fit consumer, mobile, and API scenarios.


Hands-on exercises

These are meant to be done, not just read.


  1. Decode a real assertion. Install a SAML tracer browser extension, sign in to any SAML-protected application you use, and capture the flow. Find the AuthnRequest and the assertion, base64-decode the assertion, and label its Subject, Conditions, AuthnStatement, and AttributeStatement in the live XML.
  2. Identify the bindings. In the same capture, confirm which binding carried the AuthnRequest and which carried the assertion, and check it matches the Redirect-then-POST pattern. Look at NotOnOrAfter to see how short the assertion’s life really is.
  3. Stand up a federation. Use a public sandbox such as samltest.id to play both roles: register a test SP, upload metadata, and run an SP-initiated sign-in end to end. Then break it on purpose, change the audience or mismatch a certificate, and watch the SP reject the assertion.
  4. Audit a configuration. You inherit an SP that checks only the outer response signature, accepts assertions valid for 24 hours, and has no AudienceRestriction. List every problem and the exact change for each.
  5. Design a B2B onboarding. A partner needs its employees to reach your application through their own IdP. Sketch the metadata exchange, the NameID format you’d choose and why, the three attributes you’d map, and how you’d handle their certificate rotation.
  6. Choose the protocol. Pick an application you reach through SAML and check whether it also offers OIDC. Decide which you’d use for a brand-new internal web application and which for a B2B partner integration, and justify each in two sentences.

Three questions to test yourself

  1. An SP accepts a SAML assertion and reads the user’s groups to grant administrator access, but checks the signature only on the outer response, not on the assertion. What kind of attack does this invite, and what exactly should the SP check instead?
  2. A colleague enables IdP-initiated SSO for a finance application because the launchpad is convenient. What’s the security objection, and what would you recommend?
  3. Explain why SAML uses HTTP-Redirect for the AuthnRequest but HTTP-POST for the assertion, and what HTTP-Artifact changes about where the assertion travels.

Frequently asked questions

What is SAML 2.0?

SAML 2.0, the Security Assertion Markup Language, is a 2005 OASIS standard for federated authentication. It lets an identity provider vouch for a user with a cryptographically signed XML assertion, so the user can sign in to a service provider without that service ever seeing their password. It made enterprise web single sign-on possible and is still everywhere in corporate and B2B SaaS.

What is the difference between an IdP and an SP in SAML?

The identity provider (IdP) authenticates the user and issues the assertion; it's usually the company's directory-backed sign-in, such as Entra ID, Okta, or ADFS. The service provider (SP) is the application the user wants, which trusts the IdP's assertion instead of running its own sign-in. The user authenticates once at the IdP and gets into many SPs.

What is the difference between SP-initiated and IdP-initiated SSO?

In SP-initiated SSO the user starts at the application, which sends them to the IdP to authenticate and back with an assertion; it's the most common and safest flow. In IdP-initiated SSO the user starts at an IdP portal and clicks an application tile, so the IdP sends an unsolicited assertion to the SP. IdP-initiated is convenient but more exposed to replay, and is discouraged for sensitive applications.

What is a SAML assertion?

A SAML assertion is the signed XML document an IdP issues to vouch for a user. It contains a Subject (who the user is), Conditions (when it's valid and which SP it's for), an AuthnStatement (how and when the user authenticated), and an AttributeStatement (attributes such as email, department, or groups). The SP checks the signature and conditions, then trusts the contents to start a session.

How do SAML signing and encryption differ?

Signing, with XML Signature, proves the assertion is genuine and unaltered; the SP checks it with the IdP's public certificate from metadata, and in practice it's mandatory. Encryption, with XML Encryption, hides the contents from everyone except the intended SP and is optional, used when attributes are sensitive. Signing protects integrity and authenticity; encryption protects confidentiality.

Is SAML still relevant compared to OAuth and OIDC?

Yes, within its niche. SAML is still the default for workforce single sign-on and B2B federation, where mature identity providers, compliance requirements, and existing application support make it the easiest path. For consumer sign-in, mobile apps, and API authorization, the lighter JSON-based OAuth 2.0 and OpenID Connect have largely won, so the two coexist.