Senior 7 min · June 25, 2026

SSO and SAML: Stop Copy-Pasting Auth Code and Fix Your Login Once

SSO and SAML explained for production engineers.

N
Naren Founder & Principal Engineer

20+ years shipping large-scale distributed systems. Notes here come from systems that actually shipped.

Follow
Production
production tested
June 25, 2026
last updated
1,663
articles · all by Naren
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer

SAML is an XML-based protocol for exchanging authentication and authorization data between an identity provider and a service provider. It's the backbone of enterprise SSO. You configure an IdP (like Okta or ADFS) to issue SAML assertions, and your app (the SP) validates those assertions to grant access.

✦ Definition~90s read
What is SSO and SAML?

SSO (Single Sign-On) lets users log in once and access multiple applications. SAML (Security Assertion Markup Language) is the XML-based protocol that enables SSO by exchanging authentication and authorization data between an identity provider (IdP) and a service provider (SP).

Think of SAML like a VIP pass at a conference.
Plain-English First

Think of SAML like a VIP pass at a conference. You show your ID at the front desk (the identity provider), and they give you a stamped wristband (the SAML assertion). You then walk into any session (service provider) and just flash the wristband — no need to show your ID again. The wristband has a hologram (digital signature) so no one can fake it.

Every company I've worked at has had a 'login incident' that woke someone up at 3 AM. Usually it's because someone copy-pasted SAML code from a blog post without understanding the clock skew check. SSO is supposed to make life easier, but misconfigured SAML is a silent killer — users can't log in, and you have no idea why because the error messages are garbage.

The problem SAML solves is simple: you don't want every app to manage its own passwords. You want one central authority (the IdP) that says 'this user is authenticated' and every other app trusts that. Without SAML, you either build a custom SSO protocol (please don't) or force users to log in to each app separately (which they hate).

By the end of this, you'll be able to configure SAML SSO in a production app, debug the three most common failures (clock skew, unsigned assertions, and wrong audience), and explain to your boss why you chose SAML over OIDC without sounding like a Wikipedia article.

Why SAML Exists: The Password Proliferation Problem

Before SAML, every app had its own login. Users had 50 passwords, so they reused 'password123' everywhere. IT admins couldn't revoke access centrally — they had to delete accounts in 20 different systems. SAML solved this by separating authentication (the IdP's job) from authorization (the SP's job). The IdP tells the SP 'this user is who they say they are' via a signed XML document. The SP trusts that document because it's signed with the IdP's private key.

The key insight: SAML is about trust, not just data exchange. The SP doesn't ask the IdP 'is this user valid?' every time. Instead, the IdP gives the SP a self-contained assertion that the SP can verify independently. This means the SP doesn't need network access to the IdP at runtime — it just needs the IdP's public key and a valid clock.

Without SAML, you'd have to build a shared session database or use something like OAuth 2.0 with a token introspection endpoint (which requires network calls). SAML's assertion model is more resilient to network failures, but it's also more complex to debug because the assertion is a blob of XML with strict schema rules.

SamlAssertionFlow.systemdesignSYSTEMDESIGN
1
2
3
4
5
6
7
8
9
10
11
12
// io.thecodeforge — System Design tutorial

// SAML assertion flow: IdP -> Browser -> SP
// 1. User requests protected resource at SP
// 2. SP redirects user to IdP with SAML AuthnRequest
// 3. User authenticates at IdP (password, MFA, etc.)
// 4. IdP generates SAML Response containing Assertion
// 5. Browser POSTs SAML Response to SP's ACS URL
// 6. SP validates signature, timestamps, audience, etc.
// 7. SP creates local session and redirects to original resource

// Key: The assertion is self-contained. No backchannel call to IdP needed.
Output
User -> SP: GET /protected
SP -> User: 302 Redirect to IdP with SAMLRequest
User -> IdP: POST credentials
IdP -> User: 200 with HTML form containing SAMLResponse
User -> SP: POST /acs with SAMLResponse
SP -> User: 302 Redirect to /protected (with session cookie)
Senior Shortcut:
The SAML response is a base64-encoded, deflated XML document. When debugging, decode it with echo '<base64>' | base64 -d | xmllint --format -. You'll see the actual timestamps, issuer, and signature — 90% of issues are visible right there.
SAML SSO Flow: AuthnRequest to Response Validation THECODEFORGE.IO SAML SSO Flow: AuthnRequest to Response Validation Core steps in SAML authentication from request to assertion check User Initiates Login SP redirects user to IdP with AuthnRequest IdP Authenticates User IdP validates credentials and generates SAML Response SAML Response Sent to SP POST via browser with signed assertion Validate Signature Check XML signature using IdP public cert Validate Conditions Check NotBefore, NotOnOrAfter, Audience, Recipient Session Created SP establishes local session for user ⚠ Missing audience or recipient check allows token reuse Always validate both AudienceRestriction and Destination attributes THECODEFORGE.IO
thecodeforge.io
SAML SSO Flow: AuthnRequest to Response Validation
Sso Saml

SAML vs OIDC: When to Use Each in Production

The classic mistake: using SAML for a mobile app. SAML was designed for browser-based SSO using HTTP POST bindings. It doesn't work well with native apps because there's no browser redirect flow that returns to the app. OIDC (OpenID Connect) is built for this — it uses JWTs and REST APIs.

Use SAML when: (1) You're in an enterprise environment with existing IdPs like ADFS, Okta, or Azure AD. (2) You need to support SAML-based federation (e.g., government or healthcare). (3) Your app is web-based and users access it via browsers.

Use OIDC when: (1) You're building a new app from scratch. (2) You have mobile or single-page apps. (3) You want simpler JSON tokens instead of XML. (4) You need fine-grained scopes and API access.

The trade-off: SAML is more mature and has better enterprise support, but OIDC is simpler and more modern. I've seen teams waste weeks trying to make SAML work in a mobile app — don't be that team.

Production Trap:
Don't use SAML for APIs. SAML assertions are meant for browser sessions, not API authorization. If you need to secure APIs, use OAuth 2.0 with bearer tokens. I've seen teams try to pass SAML assertions in HTTP headers — it's a nightmare of parsing and security holes.
SAML vs OIDC: Choose Your SSO ProtocolTHECODEFORGE.IOSAML vs OIDC: Choose Your SSO ProtocolBrowser vs native app authentication patternsSAMLXML-based assertions, POST bindingsDesigned for browser-based SSOHeavy: complex metadata exchangePoor fit for mobile/native appsOIDCJWT-based tokens, REST APIsBuilt for native & mobile appsLightweight: simple client configStandard for consumer SSOUse SAML for enterprise web apps; OIDC for mobile & APIsTHECODEFORGE.IO
thecodeforge.io
SAML vs OIDC: Choose Your SSO Protocol
Sso Saml

The SAML Handshake: AuthnRequest and Response Flow

The SAML flow starts when an unauthenticated user tries to access a protected resource on the SP. The SP generates an AuthnRequest — an XML document that tells the IdP what the SP expects (e.g., which SAML version, what binding to use, and where to send the response). The SP redirects the user to the IdP with this request.

The IdP authenticates the user (via password, MFA, etc.) and generates a SAML Response. This response contains an Assertion — the actual statement that the user is authenticated. The assertion includes: the user's identifier (NameID), the issuer (IdP entity ID), the audience (SP entity ID), timestamps (NotBefore and NotOnOrAfter), and optionally attributes (email, roles).

The IdP signs the assertion (or the entire response) with its private key. The SP validates the signature using the IdP's public certificate. If the signature is valid, the timestamps are within range, and the audience matches, the SP creates a local session and redirects the user to the original resource.

The critical detail: the SP must have the IdP's public certificate configured. If the certificate changes (e.g., rotation), all SPs must be updated. This is a common source of production outages.

SamlAuthnRequest.systemdesignSYSTEMDESIGN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// io.thecodeforge — System Design tutorial

// Example SAML AuthnRequest (simplified)
// SP generates this and sends to IdP via HTTP Redirect binding

<samlp:AuthnRequest
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    ID="_abc123"
    Version="2.0"
    IssueInstant="2025-03-15T10:00:00Z"
    Destination="https://idp.example.com/sso"
    AssertionConsumerServiceURL="https://sp.example.com/acs"
    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
  <saml:Issuer>https://sp.example.com/metadata</saml:Issuer>
  <samlp:NameIDPolicy
      Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
      AllowCreate="true"/>
</samlp:AuthnRequest>

// The SP must sign this request if the IdP requires it (common in production).
// The signature is added as a separate XML element or query parameter.
Output
AuthnRequest sent to IdP. IdP responds with SAMLResponse containing Assertion.
Interview Gold:
Interviewers love asking: 'What happens if the SP doesn't sign the AuthnRequest?' Answer: The IdP may reject it (if configured to require signatures) or accept it (if not). In production, always sign the AuthnRequest to prevent man-in-the-middle attacks. The IdP's metadata tells you if it requires signatures.
SAML Handshake: AuthnRequest & ResponseTHECODEFORGE.IOSAML Handshake: AuthnRequest & ResponseBrowser-based SSO flow between SP and IdPUser requests resourceUnauthenticated user hits SP protected pageSP sends AuthnRequestXML doc with version, binding, ACS URLIdP authenticates userUser logs in at identity providerIdP returns SAML ResponseXML assertion signed with IdP private keySP validates & logs inChecks signature, conditions, audience⚠ Missing signature validation = forged login allowedTHECODEFORGE.IO
thecodeforge.io
SAML Handshake: AuthnRequest & Response
Sso Saml

Validating SAML Responses: The Four Checks You Must Implement

When your SP receives a SAML Response, you must validate four things. Miss any, and you're vulnerable to attacks or login failures.

  1. Signature validation: Verify the XML signature using the IdP's public certificate. This ensures the response wasn't tampered with. Use a library like opensaml or python3-saml — don't roll your own XML signature verification.
  2. Timestamp validation: Check NotBefore and NotOnOrAfter conditions. The current time must be between these two timestamps. Allow a clock skew of up to 5 minutes (configurable). If the assertion is expired, reject it.
  3. Audience restriction: The Audience element in the assertion must match your SP's entity ID. This prevents an assertion issued for one SP from being used on another.
  4. Recipient check: The Recipient attribute in the SubjectConfirmationData must match your ACS URL. This prevents assertion replay on a different endpoint.

I've seen production outages caused by each of these. The most common: clock skew (fix with NTP monitoring) and audience mismatch (fix by double-checking entity IDs in both IdP and SP config).

SamlResponseValidation.systemdesignSYSTEMDESIGN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// io.thecodeforge — System Design tutorial

// Pseudocode for SAML response validation
// Using a library like python3-saml or opensaml

function validateSamlResponse(samlResponse, idpCert, spEntityId, acsUrl):
    // 1. Verify XML signature
    if not verifySignature(samlResponse, idpCert):
        throw "Signature validation failed"
    
    // 2. Extract assertion
    assertion = extractAssertion(samlResponse)
    
    // 3. Check timestamps with clock skew tolerance
    now = currentTimeUTC()
    notBefore = assertion.conditions.notBefore
    notOnOrAfter = assertion.conditions.notOnOrAfter
    if now < notBefore - 5 minutes or now > notOnOrAfter + 5 minutes:
        throw "Assertion expired or not yet valid"
    
    // 4. Check audience
    if assertion.conditions.audienceRestriction.audience != spEntityId:
        throw "Audience mismatch"
    
    // 5. Check recipient
    subjectConfirmation = assertion.subject.subjectConfirmation
    if subjectConfirmation.method != "urn:oasis:names:tc:SAML:2.0:cm:bearer":
        throw "Unsupported confirmation method"
    if subjectConfirmation.subjectConfirmationData.recipient != acsUrl:
        throw "Recipient mismatch"
    
    // 6. Extract user identifier
    nameId = assertion.subject.nameID
    attributes = extractAttributes(assertion)
    
    return { nameId, attributes }
Output
Returns user identity if all checks pass. Throws specific error on failure.
Never Do This:
Never skip signature validation in development and forget to enable it in production. I've seen a team deploy SAML without signature verification — an attacker could forge assertions and log in as any user. Always validate signatures, even in dev, because your dev IdP might sign responses anyway.

Configuring Your SP for SAML: The Metadata Dance

Every SAML deployment starts with exchanging metadata. The IdP has metadata (entity ID, SSO URL, public certificate). The SP has metadata (entity ID, ACS URL, public certificate). You configure each side with the other's metadata.

The IdP's metadata is usually available at a URL like https://idp.example.com/metadata. It's an XML file containing the IdP's entity ID, single sign-on service URL, and X.509 certificate. You import this into your SP configuration.

Your SP's metadata must be registered with the IdP. It includes your entity ID, ACS URL, and optionally your SP's certificate (if you sign AuthnRequests). The IdP uses this to know where to send responses and which SP is requesting authentication.

The gotcha: metadata URLs change. If the IdP rotates its certificate, the metadata URL updates. But your SP might have cached the old metadata. Always fetch metadata dynamically with a cache TTL (e.g., 24 hours) instead of hardcoding it. I've seen outages because someone hardcoded a certificate that expired.

SpMetadata.systemdesignSYSTEMDESIGN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// io.thecodeforge — System Design tutorial

// Example SP metadata XML
// This is what you register with the IdP

<EntityDescriptor
    xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
    entityID="https://sp.example.com/metadata">
  <SPSSODescriptor
      protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <KeyDescriptor use="signing">
      <KeyInfo>
        <X509Data>
          <X509Certificate>MIID... (base64 cert)</X509Certificate>
        </X509Data>
      </KeyInfo>
    </KeyDescriptor>
    <AssertionConsumerService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
        Location="https://sp.example.com/acs"
        index="0"
        isDefault="true"/>
  </SPSSODescriptor>
</EntityDescriptor>

// The entityID must be unique and match what the IdP expects.
// The ACS Location is where the IdP sends the SAML Response.
Output
SP metadata XML. IdP imports this to know how to send assertions to your SP.
Senior Shortcut:
Use a metadata URL instead of uploading XML files. Most IdPs support fetching SP metadata from a URL. This way, when you update your certificate, you just update the metadata endpoint — the IdP picks it up automatically. Set up health checks on the metadata URL to catch issues early.

Single Logout (SLO): The Feature Everyone Forgets

Single Logout (SLO) is the SAML feature that lets a user log out of all SPs by logging out of the IdP. It's rarely implemented correctly because it's complex: the IdP sends a LogoutRequest to each SP, and each SP must respond. If any SP is down, the logout fails.

The SLO flow: User clicks logout at SP. SP sends a LogoutRequest to the IdP. IdP terminates the session and sends LogoutRequests to all other SPs that the user has active sessions with. Each SP responds with a LogoutResponse. The IdP then sends a final response to the original SP.

In practice, SLO is unreliable. SPs might be offline, or the user might have multiple browser tabs. Many organizations skip SLO and rely on session timeouts instead. If you must implement SLO, use asynchronous notifications (e.g., a message queue) rather than synchronous HTTP calls, and accept that some SPs might not log out immediately.

The classic mistake: implementing SLO with synchronous HTTP calls and blocking the user's logout until all SPs respond. This leads to timeouts and a poor user experience.

SloFlow.systemdesignSYSTEMDESIGN
1
2
3
4
5
6
7
8
9
10
11
12
// io.thecodeforge — System Design tutorial

// SLO flow (simplified)
// 1. User clicks logout at SP1
// 2. SP1 sends LogoutRequest to IdP
// 3. IdP terminates session, then sends LogoutRequest to SP2 and SP3
// 4. SP2 and SP3 terminate sessions and send LogoutResponse to IdP
// 5. IdP sends final LogoutResponse to SP1
// 6. SP1 shows logout confirmation

// In production, use a message queue for step 3-4 to avoid blocking.
// If an SP is down, log the error and proceed — don't block the user.
Output
User is logged out of all SPs (best effort).
Production Trap:
Don't rely on SLO for security. If a user's session is compromised, SLO might not reach all SPs. Use short session timeouts (e.g., 15 minutes) and force re-authentication for sensitive actions. SLO is a convenience feature, not a security control.

Debugging SAML: The Tools and Techniques That Actually Work

When SAML breaks, you need to see the actual XML. The browser's developer tools are your friend. Use the Network tab to capture the POST request to your ACS URL. The SAMLResponse parameter contains the base64-encoded assertion. Decode it and format the XML.

Tools: (1) SAML-tracer browser extension (Firefox/Chrome) — intercepts SAML messages and decodes them automatically. (2) base64 -d and xmllint for command-line decoding. (3) Online SAML decoders (but be careful with sensitive data — use local tools).

Common issues: (1) Clock skew — compare NotBefore and NotOnOrAfter with server time. (2) Signature failure — check that the IdP's certificate is correct and the signature algorithm matches (e.g., RSA-SHA256). (3) Audience mismatch — ensure the Audience element matches your SP's entity ID exactly.

I once spent 4 hours debugging a signature failure only to find that the IdP had rotated its certificate and the SP was using the old one. The fix: automate certificate fetching from the IdP's metadata URL.

SamlDebugCommands.systemdesignSYSTEMDESIGN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// io.thecodeforge — System Design tutorial

// Decode SAML response from base64 and format XML
$ echo 'PHNhbWxwOlJlc3BvbnNl...' | base64 -d | xmllint --format -

// Check clock skew between SP and IdP
$ ntpdate -q idp.example.com
server 203.0.113.1, stratum 2, offset 0.002345, delay 0.04321

// Verify IdP certificate
$ openssl x509 -in idp-cert.pem -text -noout

// Test signature verification (if you have the signed assertion)
$ xmlsec1 --verify --pubkey-cert-pem idp-cert.pem signed-assertion.xml

// Fetch IdP metadata
$ curl -s https://idp.example.com/metadata | xmllint --format -
Output
Decoded XML, clock offset, certificate details, verification result, metadata XML.
Senior Shortcut:
Add a debug endpoint to your SP that logs the raw SAML response (without persisting it). In production, log only the assertion ID and timestamps — not the full XML (PII concerns). In staging, log the full decoded XML for debugging.

When Not to Use SAML: The Overkill Scenarios

SAML is overkill for: (1) Internal microservices communicating via REST APIs — use OAuth 2.0 client credentials or mutual TLS. (2) Consumer-facing apps where users don't have enterprise accounts — use social login (Google, Facebook) via OIDC. (3) Simple authentication for a single app — just use a session cookie with a password hash.

SAML adds complexity: XML parsing, signature verification, metadata management, clock synchronization. If you don't need enterprise federation, don't use it. I've seen startups waste weeks implementing SAML because 'it's the enterprise standard' when they had zero enterprise customers.

The rule of thumb: use SAML only if you have an existing IdP (Okta, ADFS, Azure AD) that you must integrate with. If you're building a new system, use OIDC. It's simpler, more secure by default, and works with mobile apps.

Interview Gold:
Interviewers ask: 'When would you choose SAML over OIDC?' The answer: when the customer mandates it (enterprise), or when you need to integrate with legacy IdPs that don't support OIDC. Otherwise, OIDC is almost always the better choice.
● Production incidentPOST-MORTEMseverity: high

The 3 AM Clock Skew That Killed Login

Symptom
All users in Europe couldn't log in for 45 minutes. US users were fine. Error logs showed 'NotOnOrAfter condition not met'.
Assumption
We assumed the IdP was down or the SP certificate had expired.
Root cause
The SP server's NTP daemon had crashed, causing its clock to drift 6 minutes behind. SAML assertions have a NotOnOrAfter timestamp (usually 5 minutes from issuance). The SP thought every assertion was expired. US users were on a different SP instance with correct time.
Fix
Restarted NTP daemon: systemctl restart ntp. Added monitoring for clock skew via Prometheus node_exporter's node_timex_offset_seconds metric. Set alert if offset > 1 second.
Key lesson
  • Always monitor clock skew between IdP and SP.
  • A 5-minute tolerance is standard, but drift happens faster than you think.
Production debug guideSystematic recovery paths for the failure modes engineers actually hit.3 entries
Symptom · 01
Users redirected to IdP but never come back to SP
Fix
1. Check ACS URL in IdP config matches SP's actual ACS endpoint exactly (including trailing slash). 2. Verify SP metadata is correctly registered. 3. Check IdP logs for errors.
Symptom · 02
SAML response rejected with 'Signature validation failed'
Fix
1. Verify SP has the correct IdP public certificate. 2. Check if the IdP signs the response or just the assertion (some libraries require the whole response to be signed). 3. Use xmlsec1 to manually verify the signature.
Symptom · 03
Users get 'Invalid SAML Response' after IdP redirect
Fix
1. Decode the SAMLResponse and check timestamps (NotBefore, NotOnOrAfter). 2. Compare server time with assertion timestamps. 3. Check audience and recipient values.
★ SSO and SAML Triage Cheat SheetFirst-response commands for when things go wrong — copy-paste ready.
Users get 'NotOnOrAfter condition not met'
Immediate action
Check clock skew between SP and IdP
Commands
ntpdate -q idp.example.com
date && curl -s https://idp.example.com/metadata | grep -oP 'NotOnOrAfter="\K[^"]+'
Fix now
Restart NTP: systemctl restart ntp. Add monitoring for clock offset.
Signature validation failed+
Immediate action
Verify IdP certificate and signature algorithm
Commands
openssl x509 -in idp-cert.pem -text -noout | grep 'Signature Algorithm'
echo 'SAMLResponse' | base64 -d | xmlsec1 --verify --pubkey-cert-pem idp-cert.pem
Fix now
Update IdP certificate from metadata URL. Ensure algorithm matches (e.g., RSA-SHA256).
Audience mismatch error+
Immediate action
Compare SP entity ID in IdP config vs assertion
Commands
echo 'SAMLResponse' | base64 -d | xmllint --xpath '//*[local-name()="Audience"]/text()' -
cat sp-metadata.xml | grep entityID
Fix now
Update IdP config with correct SP entity ID. Ensure no trailing slash mismatch.
User redirected to IdP but no SAMLResponse received+
Immediate action
Check ACS URL in IdP config
Commands
curl -s https://sp.example.com/metadata | xmllint --xpath '//*[local-name()="AssertionConsumerService"]/@Location' -
Check IdP logs for 'Invalid ACS URL' or similar
Fix now
Update ACS URL in IdP to match exactly, including protocol and trailing slash.
Feature / AspectSAMLOIDC
Token formatXML (SAML Assertion)JSON (JWT)
Transport bindingHTTP POST / RedirectREST API (JSON)
Native app supportPoor (requires browser)Excellent (native flows)
Enterprise adoptionVery high (ADFS, Okta)Growing (Google, Microsoft)
Session managementIdP-initiated logout complexRP-initiated logout simpler
Debugging difficultyHigh (XML signatures, clock skew)Low (JWT inspection tools)

Key takeaways

1
SAML is about trust via signed XML assertions
the SP validates the assertion independently without calling the IdP at runtime.
2
Clock skew is the #1 cause of SAML failures in production. Monitor it with NTP and set alerts on offset > 1 second.
3
Always validate signature, timestamps, audience, and recipient. Skipping any one opens a security hole or causes login failures.
4
For new systems, prefer OIDC over SAML. SAML is only necessary when integrating with enterprise IdPs that mandate it.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
How does SAML handle replay attacks?
Q02SENIOR
When would you choose SAML over OIDC in a production system?
Q03SENIOR
What happens if the IdP's certificate expires and you don't update it?
Q04JUNIOR
What is a SAML assertion and what are its key components?
Q05SENIOR
You're debugging a SAML login failure. The user is redirected to the IdP...
Q06SENIOR
How would you design SAML SSO for a multi-tenant SaaS application?
Q01 of 06SENIOR

How does SAML handle replay attacks?

ANSWER
SAML prevents replay attacks using the NotBefore and NotOnOrAfter timestamps combined with an assertion ID. The SP should also cache assertion IDs and reject duplicates. The SubjectConfirmationData with Recipient and InResponseTo (if using AuthnRequest) adds another layer.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
What is SAML and how does it work for SSO?
02
What's the difference between SAML and OAuth?
03
How do I debug a SAML login failure?
04
What happens if the IdP certificate expires?
N
Naren Founder & Principal Engineer

20+ years shipping large-scale distributed systems. Notes here come from systems that actually shipped.

Follow
Verified
production tested
June 25, 2026
last updated
1,663
articles · all by Naren
🔥

That's Security. Mark it forged?

7 min read · try the examples if you haven't

Previous
Clean Architecture
11 / 13 · Security
Next
Authorization: RBAC vs ABAC