SAML 2.0
SAML 2.0
Section titled “SAML 2.0”Standards
Section titled “Standards”- SAML 2.0 Core
- SAML 2.0 Bindings
- SAML 2.0 Profiles
- SAML 2.0 Metadata
- W3C XML Signature (Exclusive Canonicalization, enveloped signatures)
Two Separate Entities
Section titled “Two Separate Entities”ProtocolSoup runs a SAML identity provider and a SAML service provider as two distinct entities. Each has its own entityID, its own RSA signing key with a self-signed X.509 certificate, and its own metadata.
| Role | entityID (also its metadata location) |
|---|---|
| Identity provider | {BASE_URL}/saml/idp/metadata |
| Service provider | {BASE_URL}/saml/sp/metadata |
Each entityID is the URL its metadata is published at (SAML Metadata Section 4.1.1). Neither role reads the other’s state. Each fetches the other’s metadata over HTTP and trusts only the signing certificate published there. A certificate carried in a message’s <ds:KeyInfo> is never trusted unless it matches that metadata.
Keys and certificates persist under {SHOWCASE_DATA_DIR}/saml/ (idp.key.pem, idp.cert.pem, sp.key.pem, sp.cert.pem). Without a data directory they are generated on each start.
Available Flows
Section titled “Available Flows”| Flow ID | Name | Description |
|---|---|---|
sp_initiated_sso |
SP-Initiated SSO | Service Provider starts the login flow |
idp_initiated_sso |
IdP-Initiated SSO | Identity Provider sends an unsolicited Response |
single_logout |
Single Logout | SP-initiated logout with signed LogoutRequest and LogoutResponse |
idp_initiated_logout |
IdP-Initiated Single Logout | The IdP, as session authority, logs the SP out (Profiles Section 4.4.3.3) |
metadata |
Metadata Exchange | SP/IdP metadata discovery and sharing |
Endpoints
Section titled “Endpoints”Identity provider
Section titled “Identity provider”| Path | Methods | Purpose |
|---|---|---|
/saml/idp/metadata |
GET | IdP EntityDescriptor (application/samlmetadata+xml) |
/saml/idp/sso |
GET, POST | SingleSignOnService (HTTP-Redirect, HTTP-POST) |
/saml/idp/login |
POST | Principal authentication; starts the IdP session and answers with the signed Response (Cancel answers AuthnFailed) |
/saml/idp/initiate |
GET | Start IdP-initiated SSO (optional RelayState) |
/saml/idp/logout |
GET | Start IdP-initiated Single Logout (session_id, binding) |
/saml/idp/slo |
GET, POST | SingleLogoutService (HTTP-Redirect, HTTP-POST); a LogoutResponse gets the outcome page |
Service provider
Section titled “Service provider”| Path | Methods | Purpose |
|---|---|---|
/saml/sp/metadata |
GET | SP EntityDescriptor (application/samlmetadata+xml) |
/saml/sp/login |
GET | Start SP-initiated SSO (binding=redirect or post, optional RelayState, force_authn=true, is_passive=true) |
/saml/sp/acs |
POST | AssertionConsumerService (HTTP-POST only); answers with the outcome page |
/saml/sp/logout |
GET | Start SP-initiated Single Logout (session_id, binding) |
/saml/sp/slo |
GET, POST | SingleLogoutService (HTTP-Redirect, HTTP-POST); a LogoutResponse gets the outcome page |
| Path | Methods | Purpose |
|---|---|---|
/saml/demo/sessions |
GET | Current sessions held by the SP (sp) and the IdP (idp), so Looking Glass can pick one to log out |
Looking Glass
Section titled “Looking Glass”Looking Glass runs every SAML flow through the real endpoints above, in a popup, so the browser follows each HTTP-Redirect and HTTP-POST hop itself. The executor adds the Looking Glass session to the first URL as lg_session. Each role carries it on to the next endpoint it sends the user agent to, outside the signed query values (SAML Bindings Section 3.4.4.1 signs only SAMLRequest/SAMLResponse, RelayState and SigAlg) and outside the Destination attribute. The capture middleware and the roles’ events therefore record every real exchange.
The endpoint that receives the last message of a flow answers with an outcome page. That is the assertion consumer service for SSO, and the initiator’s SingleLogoutService for logout. The page shows:
- the message as it arrived;
- every check the receiving role ran, with its spec reference;
- the session or status it produced.
When Looking Glass opened the window, the page also hands the outcome to it with postMessage. It addresses only the deployment’s own origin and the configured frontend origins (SHOWCASE_CORS_ORIGINS).
Signatures
Section titled “Signatures”- Enveloped XML signatures (SAML Core Section 5.4.1), RSA-SHA256, SHA-256 digests, and Exclusive Canonicalization (Section 5.4.3).
<ds:Signature>sits immediately after<saml:Issuer>. It holds a single<ds:Reference>whose URI is#plus the signed element’sID(Section 5.4.2).- Verifiers reject transforms other than enveloped-signature and exclusive canonicalization (Section 5.4.4). They also reject
<ds:Object>(Errata E91) and anyIDdeclared more than once (Section 1.3.4). - Only the signed bytes are read after verification, which defeats XML Signature Wrapping.
- The HTTP-Redirect binding carries no XML signature. The query string
SAMLRequest|SAMLResponse=…&RelayState=…&SigAlg=…is signed, and verified over the received URL-encoded values (Bindings Section 3.4.4.1).
What Each Role Checks
Section titled “What Each Role Checks”IdP, on an AuthnRequest
- The signature verifies against the SP’s metadata. An unsigned request gets a SAML error Response with status
Requester/RequestDenied, because the SP’s metadata declaresAuthnRequestsSigned="true"(Metadata Section 2.4.4, Errata E7). Destinationis checked.- The
AssertionConsumerServiceURLorAssertionConsumerServiceIndexmust be an HTTP-POST endpoint in the SP’s metadata (Profiles Section 4.1.4.1). - An unsupported
NameIDPolicygets an error Response.
IdP, identifying the principal (Profiles Section 4.1.3.4)
- The principal signs in once at the IdP. The IdP keeps an authentication session (the
saml_idp_sessioncookie, 8 hours) and answers every later AuthnRequest, and IdP-initiated SSO, from it without asking for credentials. That is the single sign-on. The assertion’sAuthnInstantis the original sign-in. ForceAuthn="true"makes the IdP ask for credentials again despite the session (Core Section 3.4.1).IsPassive="true"succeeds only from a live session. Without one, or together withForceAuthn, the IdP returnsResponder/NoPassive.- Cancel at the sign-in page returns
Responder/AuthnFailed(Profiles Section 4.1.3.5). - Single Logout ends the IdP session, so the next SSO asks for credentials (Core Section 3.7.3.2).
SP, on a Response (Profiles Sections 4.1.4.3 and 4.1.4.5)
- Delivery over HTTP-POST only.
- Response and assertion signatures are verified against the IdP’s metadata. The assertion must carry its own signature (
WantAssertionsSigned="true"). Destination,Issuer(withFormatomitted orentity) andVersionare checked.InResponseTomust match an outstanding AuthnRequest, andRelayStatemust equal the value sent with it.- At least one bearer
SubjectConfirmationmust have a matchingRecipient, an unexpiredNotOnOrAfter, noNotBeforeand a matchingInResponseTo. Conditionsmust hold their time window, and everyAudienceRestrictionmust include the SP.- An
AuthnStatementwith aSessionIndexmust be present. - The assertion ID must not be a replay.
- Clock skew is 3 minutes (SAML Core Errata E92).
- Any failed check rejects the Response.
Single Logout
- LogoutRequest and LogoutResponse must be signed on the front-channel bindings (Profiles Sections 4.4.3.1 and 4.4.3.4).
Issuer,DestinationandNotOnOrAfterare checked.- A LogoutRequest from the SP must carry a
SessionIndex(Section 4.4.4.1). InResponseToandRelayStatemust match the outstanding request.
Limits
- The bindings are HTTP-Redirect and HTTP-POST only; there is no Artifact or SOAP binding.
- There is no
EncryptedAssertionsupport. - The SP accepts unsolicited Responses.
- RelayState longer than 80 bytes is refused (Bindings Sections 3.4.3 and 3.5.3).