larsggu.me › Reference › SAML single sign-on
SAML single sign-on
SP redirect -> IdP -> signed <Assertion> POSTed to ACS URL
A browser-mediated exchange in which an identity provider issues a signed statement about a user and the application accepts it in place of its own login.
Description
SAML predates the token formats that surround it now, and it survives because it solves a specific organisational problem well: an employer wants one place where employment ends and every application to honour that immediately. The application stops holding passwords and starts trusting a signed statement.
The exchange happens through the browser. The application redirects the user to the identity provider with a request; the provider authenticates the user by whatever means the organisation requires and returns a signed assertion to the application's assertion consumer service. The assertion names the user, states when it was issued, states how long it is valid, and names the audience it was minted for.
Verification is where implementations go wrong, and the errors are consistent. The signature has to be checked against a certificate configured in advance rather than one carried in the message. The audience has to match this application. The validity window has to be enforced with a small clock tolerance rather than a generous one. The assertion identifier has to be recorded so the same assertion cannot be presented twice.
The subject identifier should be the persistent value the provider issues, not the email address in the attribute statement, for the same reason provisioning uses an immutable external identifier: addresses change, and an account keyed to one splits when it does.
Fields
| Field | Form | Meaning |
|---|---|---|
| Issuer | URI | Identifies the identity provider. Matched against configuration. |
| Signature | XML digital signature | Verified against a pre-configured certificate, never against one in the message. |
| Audience | URI | The application the assertion was minted for. Must match. |
| NotBefore / NotOnOrAfter | instants | The validity window. Enforced with a small clock tolerance. |
| NameID | persistent identifier | The stable subject. Preferred over any address attribute. |
| AssertionID | unique string | Recorded to refuse a replayed assertion. |
Example
What the application must check
POST /saml/acs HTTP/1.1 Content-Type: application/x-www-form-urlencoded SAMLResponse=<base64 of the signed Response> # accept only when all of the following hold # signature verifies against the configured certificate # Issuer equals the configured identity provider # Audience equals this application # now is inside NotBefore .. NotOnOrAfter, small tolerance # AssertionID has not been seen before
Every one of these conditions has been the single missing check in a published implementation flaw.
Failure modes
- Verifying against a certificate embedded in the response, which accepts anything self-signed.
- Skipping the audience check, so an assertion minted for one application is accepted by another.
- Allowing a wide clock tolerance, which extends the replay window far past the intent.
- Keying the account on an email attribute rather than the persistent subject identifier.
Related entries
Topic: Identity. Last modified 2026-09-06.