Most organisations run both SAML 2.0 and OpenID Connect, often for the same users, and each protocol fails in its own way when relying parties skip validation or signing keys are poorly protected. SAML is the XML-based standard that has carried enterprise web single sign-on since 2005; OpenID Connect (OIDC) is the identity layer on OAuth 2.0 that dominates mobile, API and modern SaaS integration. This guide compares how they work, gives a decision table for choosing between them, and sets out the security pitfalls that matter in practice, from XML signature wrapping to ID token validation and token-signing key theft. It is for identity architects, application owners integrating SSO, and security teams reviewing federation configurations.
Key takeaways
- Both are federation protocols, built differently. SAML passes signed XML assertions through the browser; OIDC passes signed JWT ID tokens and adds OAuth access tokens for APIs.
- Choose by client type and ecosystem, not fashion. OIDC fits native apps, single-page apps, APIs and agents; SAML remains the pragmatic choice for legacy enterprise SaaS that supports nothing else.
- SAML's biggest risk is the relying party's XML handling. Signature wrapping, accepting unsigned content and skipping Audience or Destination checks have broken many implementations.
- OIDC's biggest risks are skipped validation and weak flows. Not checking
iss,audandnonce, using the implicit flow, and mix-up between providers are the recurring faults. - The signing key is the crown jewel in both. Whoever holds the IdP's signing key can log in as anyone, as the Golden SAML attacks showed. Protect it like a tier-zero credential.
How SAML 2.0 works
SAML 2.0 was approved as an OASIS Standard in March 2005. Its core specification defines the assertion and protocol messages, and separate specifications define bindings, profiles and metadata.
- Roles: the identity provider (IdP) authenticates the user and issues assertions; the service provider (SP) consumes them and creates a local session.
- Assertion: an XML
<Assertion>with a required<Issuer>, an optional<ds:Signature>, a<Subject>with<SubjectConfirmationData>(Recipient,NotOnOrAfter,InResponseTo),<Conditions>(NotBefore,NotOnOrAfter,<AudienceRestriction>,<OneTimeUse>), and statements such as<AuthnStatement>and<AttributeStatement>.<EncryptedAssertion>protects confidentiality through intermediaries. - Protocol messages: the SP sends an
<AuthnRequest>; the IdP returns a<Response>containing the assertion;<LogoutRequest>drives Single Logout. - Bindings: HTTP Redirect (request DEFLATE-encoded in the URL, signed with
SigAlgandSignaturequery parameters), HTTP POST (base64 XML in an auto-submitted form, signature inside the XML), HTTP Artifact, SOAP, PAOS and URI. Web SSO typically uses Redirect for the request and POST for the response. - SP-initiated vs IdP-initiated: in SP-initiated SSO the user starts at the application, which sends an
AuthnRequest. In IdP-initiated SSO the IdP sends an unsolicited response, so there is no request ID for the SP to match. - Metadata: XML documents that describe each entity's endpoints, bindings and signing and encryption certificates, exchanged to establish trust.
How OpenID Connect works
OpenID Connect Core 1.0 (current text incorporating errata set 2, December 2023) adds authentication to OAuth 2.0. The OpenID Provider (OP) issues an ID token, a signed JWT that tells the relying party (RP) who authenticated and how.
- ID token claims: required
iss,sub,aud,exp,iat; commonlynonce,auth_time,acr,amr,azpandat_hash. - Flows: Authorization Code (
response_type=code, all tokens from the token endpoint), Implicit (id_tokenorid_token token) and Hybrid (code id_tokenand variants). Use Authorization Code with PKCE for all client types. - UserInfo endpoint: an HTTPS-protected resource that returns claims when presented with an access token.
- Discovery and keys: OpenID Connect Discovery publishes endpoints and the
jwks_uriat/.well-known/openid-configuration, which makes key rotation simpler than swapping SAML metadata certificates. - Logout: Back-Channel Logout 1.0 (Final, December 2023) sends a signed logout token to each RP's
backchannel_logout_uri; it must contain thehttp://schemas.openid.net/event/backchannel-logoutevent and must not contain anonce.
OIDC also gives the application OAuth access tokens to call APIs, which SAML does not. For the full OAuth picture, see the OAuth 2.0 and OpenID Connect Guide.
SAML and OIDC compared
| Aspect | SAML 2.0 | OpenID Connect |
|---|---|---|
| Standards body and date | OASIS, 2005 | OpenID Foundation, 2014 (errata set 2, 2023) |
| Token format | XML assertion, XML Signature and XML Encryption | JSON Web Token (JWS, optionally JWE) |
| Transport | Browser redirects and form POST; SOAP for artifact resolution | Browser redirect to authorisation endpoint, back-channel call to token endpoint |
| API access | Not designed for it (assertion grant via RFC 7522 is rare) | Native: OAuth access tokens and refresh tokens |
| Native and mobile apps | Awkward (ECP profile is little used) | Designed for it with Authorization Code and PKCE |
| Trust setup | Manual metadata exchange and certificate pinning | Discovery document and JWKS endpoint, dynamic registration optional |
| Replay protection | InResponseTo, NotOnOrAfter, OneTimeUse, SP replay cache | nonce, exp, state, single-use authorisation code, PKCE |
| Logout | Single Logout profile, front-channel, completion not guaranteed | Back-Channel and Front-Channel Logout specifications |
| Parsing risk | High: XML canonicalisation, signature wrapping, XXE | Lower, but JWT pitfalls (alg handling, key confusion) |
| Typical fit | Workforce SSO to enterprise SaaS and legacy apps | Workforce and customer SSO, mobile, SPAs, APIs, AI agents |
Choosing between them
| Situation | Choose | Why |
|---|---|---|
| New in-house web application | OIDC | Simpler libraries, JSON tokens, API access tokens in the same flow |
| Native mobile or desktop app | OIDC (Authorization Code + PKCE, system browser) | SAML has no practical native-app pattern |
| Single-page app calling APIs | OIDC, ideally through a backend-for-frontend | Keeps tokens out of the browser; DPoP if tokens must live there |
| SaaS that offers only SAML | SAML | Use what the vendor supports; apply the hardening below |
| SaaS offering both | Usually OIDC; SAML where your IdP's SAML integration has richer provisioning or policy features | Compare features per application, not in the abstract |
| Academic or government federation (multi-party metadata) | SAML | Many established federations publish SAML metadata aggregates |
| Services, workloads or AI agents | Neither for login; OAuth 2.0 client credentials, token exchange or workload identity federation | No interactive user; see the machine identity guides |
| Highest federation assurance (NIST FAL3) | Either, with holder-of-key assertions or bound authenticators | FAL3 requires proof of possession, not bearer assertions |
Small organisations: let the IdP's application catalogue decide and spend effort on the IdP itself (phishing-resistant MFA, admin protection). Large organisations: set a default (OIDC for new builds), keep a register of SAML integrations with certificate expiry dates, and review exceptions yearly. For workloads, see the Machine-to-Machine OAuth (Client Credentials) Guide and the Workload Identity Federation Guide.
Securing SAML deployments
XML signature wrapping, at concept level
An XML signature references the element it covers by ID. Signature wrapping (XSW) attacks exploit SPs where the code that verifies the signature and the code that reads the user's identity look at different elements: a valid signed assertion is kept in the document so the signature checks out, while a second, attacker-supplied assertion is placed where the business logic reads it. The 2012 USENIX paper "On Breaking SAML: Be Whoever You Want to Be" found critical XSW flaws in 11 of 14 SAML frameworks it examined. The defence is architectural rather than a single setting:
- Use only what was signed: process the exact element the verified signature's
Referenceresolved to, and reject documents with extra assertions. - Validate schema first: validate against local, trusted schemas before any security processing; never fetch schemas from the message.
- Select elements strictly: use absolute XPath expressions, not tag-name searches across the document.
- Ignore embedded keys: verify with the IdP certificate from configured metadata and ignore any
KeyInfoin the message. - Use a maintained library: do not write SAML parsing yourself, and patch SAML libraries promptly, because wrapping and canonicalisation flaws continue to be found.
Assertion validation an SP must perform
| Check | Element | Failure it prevents |
|---|---|---|
| Signature present and valid with the pinned IdP key | <ds:Signature> on Response and/or Assertion | Forged or modified assertions |
| Algorithm at least RSA-SHA256; reject SHA-1 | SignatureMethod, DigestMethod | Weak signature acceptance |
| Audience equals the SP entity ID | <AudienceRestriction> | Assertion for another SP being replayed here |
| Destination and Recipient equal the ACS URL | Destination, Recipient | Cross-SP replay |
| Time window | NotBefore, NotOnOrAfter | Replay of old assertions |
| Request correlation | InResponseTo | Unsolicited or injected responses |
| Assertion ID not seen before | Assertion ID, replay cache | Replay within validity window |
| Issuer matches the configured IdP | <Issuer> | Assertions from an untrusted IdP |
- Disable IdP-initiated SSO where possible: without a request to match, the SP loses login CSRF protection. If it must stay, allowlist
RelayStatetargets and enforce replay detection. - Harden the XML parser: disable DTDs and external entity resolution to remove XXE.
- Manage certificates: track signing certificate expiry, rotate with overlap, and keep IdP signing keys in an HSM.
See the SAML Security Guide for deeper SAML hardening.
Securing OIDC deployments
- Validate the ID token fully (Core Section 3.1.3.7):
issexactly matches the issuer,audcontains yourclient_id,azpif present, signature with keys from the issuer's JWKS,expin the future,iatrecent,noncematches the value you sent, andacrorauth_timewhen you requested them. - Use Authorization Code with PKCE: RFC 9700 says clients should not use the implicit grant or other response types that return access tokens in the authorisation response.
- Defend against mix-up: clients that trust more than one provider must check the issuer, using the
issauthorisation response parameter (RFC 9207) or the ID tokeniss(RFC 9700 Section 4.4). - Pin algorithms: accept only the algorithms you expect; never accept
none, and do not let a token's header pick an HMAC key from a public key. See the JWT Security Guide. - Exact redirect URIs: register exact URIs, no wildcards, and use
stateto bind the response to the browser session. - Do not use the ID token as an API credential: it is addressed to the client; APIs should accept access tokens with their own audience. Consider sender-constrained tokens, see the DPoP Guide.
- Protect client secrets: prefer
private_key_jwtfor confidential clients; a leaked secret lets anyone redeem codes.
Migration and coexistence
- Inventory: list every federated application, protocol, IdP, signing certificate expiry, whether IdP-initiated SSO is on, and the owner.
- Prioritise: start with applications that need API access or native clients, then high-risk SAML integrations with custom or unmaintained libraries.
- Build in parallel: register the OIDC client alongside the SAML integration and map the same user identifier (
subor an agreed attribute) so accounts link rather than duplicate. - Pilot: move a small user group via a separate login route; compare sign-in logs, attribute mapping and MFA enforcement.
- Cut over: switch the default login, keep SAML available but monitored for a defined period, then disable it and remove the SAML trust and certificate.
- Roll back: re-enable the SAML route at the application; because the trust was kept during the overlap, rollback is a configuration switch.
Pair either protocol with SCIM for joiner, mover and leaver changes, because neither SAML nor OIDC removes accounts on its own.
Detection and measurement
- IdP logs: new or changed federation trusts, signing certificate changes, new applications, and changes to claim or attribute mappings.
- SP and RP logs: signature failures, Audience or Destination mismatches, replayed assertion IDs,
nonceandissfailures. - Correlation: SP sign-ins with no matching IdP authentication event are a strong indicator of forged assertions (the Golden SAML pattern, ATT&CK T1606.002).
- Metrics: share of applications behind central SSO; share of new integrations using OIDC with PKCE; SAML integrations with IdP-initiated SSO enabled; signing certificates within 30 days of expiry; SP sign-ins without a matching IdP event (target zero); applications still accepting SHA-1 signatures.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev. 5 | IA-2, IA-8 | Identification and authentication of organisational and non-organisational users through federation |
| NIST SP 800-53 Rev. 5 | IA-5 | Management of signing keys and client secrets as authenticators |
| NIST SP 800-53 Rev. 5 | SC-23, AC-12 | Session authenticity and session termination, including federated logout |
| NIST SP 800-63C-4 | FAL1, FAL2, FAL3 | Assertion protection levels; FAL2 needs injection protection and a single-RP audience, FAL3 needs holder-of-key or bound authenticators |
| CIS Controls v8.1 | 6.7 Centralize Access Control | Centralising access through an SSO provider |
| ISO/IEC 27001:2022 | A.5.17, A.8.5 | Authentication information and secure authentication |
| MITRE ATT&CK | T1606.002 SAML Tokens, T1199 Trusted Relationship | Forged assertions and abuse of federation trust |
Common failure patterns
- Signature checked, wrong element used: the SP verifies a signature but reads the identity from an unsigned or wrapped assertion.
- Unsigned assertions accepted: the SP trusts any assertion when the signature element is absent, or accepts a signed Response with an unsigned assertion it never checks.
- Audience not enforced: one SP accepts assertions or ID tokens issued for another application, letting a compromise of a low-value app reach a high-value one.
- Implicit flow and lax redirect URIs: tokens in URL fragments and wildcard redirects lead to token leakage and injection.
- Stale certificates and IdP-initiated defaults: integrations break on expiry, prompting rushed fixes that disable validation, while unsolicited responses remain accepted.
- Federation trust as the soft spot: attackers who reach the IdP pivot through every connected application, as in the Taiwan autonomous AI agent cyberattack, where 84 of 85 sprayed accounts reached an internal system through an SSO bridge endpoint with no further authentication, and one government API accepted JWTs with the algorithm set to
none. Federation multiplies the value of every weak login and every lax token check, so step-up authentication and strict token validation belong at sensitive relying parties, not only at the IdP.
Lessons from incidents
In the SolarWinds supply chain compromise, attackers with on-premises administrative access reached a trusted SAML token-signing certificate and forged tokens that let them sign in as any user to federated services, without passwords or MFA prompts. Every SP validated the signature correctly; the protocol worked as designed because the key itself was stolen. The lessons apply equally to OIDC signing keys: keep token-signing keys in an HSM, treat the IdP servers as tier zero, alert on federation trust and certificate changes, rotate keys twice after suspected compromise, and correlate SP sign-ins with IdP authentication events. See the Federation and Trust Relationships Guide and the Identity Provider and SSO Security Guide.
Practitioner checklist
- Maintain a register of every SAML and OIDC integration with protocol, owner, certificate expiry and IdP-initiated status.
- Set OIDC Authorization Code with PKCE as the default for new integrations; ban the implicit flow.
- Verify each SAML SP enforces signature, Audience, Destination, Recipient, time window,
InResponseToand replay checks, and rejects SHA-1. - Verify each OIDC client validates
iss,aud,azp, signature,exp,iatandnonce, and uses exact redirect URIs. - Disable IdP-initiated SAML SSO unless there is a documented need, and allowlist
RelayStatewhere it stays. - Store IdP signing keys in an HSM, restrict who can change federation trusts, and alert on every change.
- Correlate SP or RP sign-ins with IdP authentication events and investigate gaps.
- Patch SAML and OIDC libraries on a defined cadence and test with negative cases (unsigned, wrapped, wrong audience).
- Pair SSO with SCIM provisioning so leavers lose application accounts, not just IdP access.
Standards and references
- OASIS: Assertions and Protocols for the OASIS Security Assertion Markup Language (SAML) V2.0
- OASIS: Bindings for the OASIS Security Assertion Markup Language (SAML) V2.0
- OpenID Foundation: OpenID Connect Core 1.0
- OpenID Foundation: OpenID Connect Back-Channel Logout 1.0
- IETF: RFC 9700 Best Current Practice for OAuth 2.0 Security
- NIST: SP 800-63C-4 Federation and Assertions
- OWASP: SAML Security Cheat Sheet
- USENIX: On Breaking SAML: Be Whoever You Want to Be
Related NHI Mgmt Group resources: OAuth 2.0 and OpenID Connect Guide · Identity Provider and SSO Security Guide · SAML Security Guide · Federation and Trust Relationships Guide · API Keys vs OAuth Tokens Guide