A broken SAML single sign-on integration usually shows the user a generic error page, while the real reason sits in an XML message that neither the identity provider nor the application displays. The fastest route to a fix is to decide which side rejected the exchange, capture the SAML request and response, and compare a small set of values: entity IDs, URLs, the NameID, timestamps and the signing certificate. This guide gives a symptom-led method for doing that, with the SAML 2.0 status codes, the Microsoft Entra ID AADSTS codes seen most often with SAML apps, and typical service provider library messages. It is for identity engineers, application owners and support teams who run SAML federations; for the security model and hardening see the SAML Security Guide.
Key takeaways
- First decide which side failed. An error on the identity provider's sign-in page means the AuthnRequest or the user's assignment was rejected; an error on the application after a successful sign-in means the service provider rejected the assertion.
- Capture before you change anything. A browser capture of the SAMLRequest and SAMLResponse, plus the IdP's correlation ID and timestamp, resolves most cases in minutes and stops trial and error edits.
- Five values cause most failures. Issuer or entity ID, Assertion Consumer Service URL, audience, NameID format and value, and the signing certificate account for the bulk of real SAML errors.
- Certificates expire on a schedule you already know. Signing certificate rollover is the most predictable SAML outage; the IdP tells you the date months ahead.
- Never fix by weakening validation. Turning off signature checks, accepting any audience or widening clock tolerance to hours makes the error go away by removing the controls that stop forged assertions.
Locate the failure: which side rejected the exchange
In service provider (SP) initiated SSO, the application sends an AuthnRequest to the identity provider (IdP), the user authenticates, and the IdP posts a signed Response containing an Assertion to the SP's Assertion Consumer Service (ACS) URL. In IdP-initiated SSO there is no AuthnRequest, so the Response has no InResponseTo value. Each stage fails in a characteristic way.
| Where the user sees the error | What failed | Typical evidence | Who fixes it |
|---|---|---|---|
| IdP sign-in page, before credentials | The IdP could not match or accept the AuthnRequest | Unknown issuer, reply URL mismatch, unsupported binding, unexpected destination | IdP administrator, sometimes the app owner |
| IdP sign-in page, after credentials | User not permitted, policy blocked, authentication context not met | Assignment errors, Conditional Access blocks, NoAuthnContext | IdP administrator |
| Application page, after redirect | The SP rejected the Response or Assertion | Signature, audience, recipient, time window, NameID or missing attribute errors in the SP log | Application owner or vendor, using values from the IdP |
| Application loads but user is wrong or has no rights | Assertion valid but mapped incorrectly | NameID does not match the SP account, role claim missing | Both: claims at the IdP, mapping at the SP |
Capture the evidence
- Record the error identifiers: in Microsoft Entra ID copy the message from the error page including the CorrelationID and Timestamp; other IdPs show an equivalent request or trace ID. These locate the sign-in event in the IdP logs.
- Capture the messages: use the IdP's own tooling where it exists (Entra's Test single sign-on page with the My Apps Secure Sign-in Extension downloads the SAML request and response) or a browser developer tools network capture. The HTTP-POST binding carries a base64 encoded SAMLResponse form field; the HTTP-Redirect binding carries a deflated, base64 and URL encoded SAMLRequest query parameter.
- Decode and read: decode locally rather than in an online tool, because a captured assertion is a live bearer credential until it expires.
- Check the SP log: most SP libraries log the precise validation failure even when the user sees a generic page.
- Compare against configuration: lay the decoded values next to the IdP application settings and the SP metadata, field by field, using the table in the next section.
The values to compare
| Element | Must match | Typical failure message (example source) |
|---|---|---|
| AuthnRequest Issuer | The SP entity ID (Identifier) configured at the IdP | Entra AADSTS700016: "The application wasn't found in the directory/tenant", or AADSTS65005, whose description notes that a SAML app may have been configured with the wrong Identifier (Entity) |
| AuthnRequest AssertionConsumerServiceURL | A reply URL registered for the app at the IdP | Entra AADSTS50011: "The reply address is missing, misconfigured, or doesn't match reply addresses configured for the app." |
| AuthnRequest Destination | The IdP's SSO service URL | Entra AADSTS75008: "The request from the app was denied since the SAML request had an unexpected destination." |
| Response Destination and SubjectConfirmationData Recipient | The ACS URL the SP is actually listening on, including scheme, host, port and path | python3-saml: "The response was received at %s instead of %s" |
| AudienceRestriction / Audience | The SP's own entity ID | python3-saml: "%s is not a valid audience for this Response" |
| Response and Assertion Issuer | The IdP entity ID in the SP's IdP metadata | python3-saml: "Invalid issuer in the Assertion/Response (expected ..., got ...)" |
| Signature and KeyInfo | The IdP signing certificate the SP trusts | python3-saml: "Signature validation failed. SAML Response rejected" |
| Conditions NotBefore / NotOnOrAfter | The SP's current time, within its allowed drift | python3-saml: "Could not validate timestamp: not yet valid. Check system clock." |
| InResponseTo | The ID of the AuthnRequest the SP sent in this browser session | python3-saml: "The InResponseTo of the Response: ..., does not match the ID of the AuthNRequest sent by the SP: ..." |
| NameID value and Format | The identifier the SP uses to find the account | SP-specific "user not found", or SAML status InvalidNameIDPolicy from the IdP |
Microsoft notes that Entra error texts can change; check the current wording at login.microsoftonline.com/error?code= followed by the number.
SAML 2.0 status codes
When the IdP returns a Response that is not a success, the Status element carries a top-level code and often a second-level code. These are defined in the OASIS SAML 2.0 core specification, section 3.2.2.2.
| Status code (urn:oasis:names:tc:SAML:2.0:status:) | Meaning | Usual cause in practice |
|---|---|---|
| Requester (top level) | The requester made an error | Bad AuthnRequest: wrong issuer, ACS URL, binding or NameID policy |
| Responder (top level) | The responder made an error | IdP fault or policy refusal; read the second-level code and StatusMessage |
| VersionMismatch (top level) | Message version incorrect | SAML 1.1 SP talking to a SAML 2.0 only endpoint |
| AuthnFailed | The principal could not be authenticated | User failed authentication at the IdP |
| InvalidNameIDPolicy | Requested name identifier policy not supported | SP requests a NameID Format the IdP is not configured to release, or AllowCreate=false with no existing persistent ID |
| NoAuthnContext | Requested authentication context cannot be met | SP demands a specific RequestedAuthnContext (for example password protected transport) while the user signed in with another method |
| NoPassive | Cannot authenticate passively | SP sent IsPassive=true and the user has no IdP session |
| RequestDenied | Responder chose not to respond | IdP policy refusal, often user not assigned to the application |
| UnknownPrincipal | Principal not recognised | Subject in the request does not exist at the IdP |
| UnsupportedBinding | Cannot use the requested binding | SP requested a ProtocolBinding the IdP has not enabled for the ACS URL |
| PartialLogout | Logout not propagated to all participants | Single logout reached some SPs only; expected in many estates |
Symptom guide: common errors, causes and fixes
Application not found or reply URL mismatch
- Symptom: the IdP shows an error before or straight after the user enters credentials (Entra AADSTS700016 or AADSTS50011).
- Likely causes, most common first: the SP sends an entity ID that differs from the Identifier at the IdP (trailing slash, http versus https, tenant specific suffix); the app was moved to a new hostname and the ACS URL was not added; the request went to the wrong tenant or IdP.
- Diagnose: read Issuer and AssertionConsumerServiceURL in the decoded AuthnRequest and compare character by character with the IdP configuration.
- Fix: correct the value at whichever side is wrong; add new reply URLs rather than replacing old ones during a migration.
- Prevent: exchange metadata rather than typing values, and include SAML settings in the application's change checklist.
Signature validation failed
- Symptom: sign-in succeeds at the IdP, the application rejects the response, and the SP log reports a signature failure or "No Signature found".
- Likely causes: the IdP signing certificate was rolled over and the SP still trusts the old one; the SP expects a signed assertion but the IdP signs only the response, or the reverse; a proxy or load balancer re-encoded the POST body; the SP rejects SHA-1 or the IdP is set to SHA-1 for a legacy app.
- Diagnose: compare the certificate in the Response KeyInfo (or the IdP metadata) with the one configured at the SP by thumbprint; check whether the Signature element sits on Response, Assertion or both.
- Fix: upload the current IdP certificate to the SP, or align the signing option. In Entra the Signing Option values are Sign SAML response, Sign SAML response and assertion, and Sign SAML assertion; Signing Algorithm should only be changed to SHA-1 when the application cannot accept anything else.
- Prevent: see the certificate rollover section below.
Audience, recipient or destination rejected
- Symptom: the SP log names the audience, recipient or destination as invalid.
- Likely causes: the SP sits behind a reverse proxy or TLS terminator and computes its own URL as http or with an internal host name; the IdP Identifier was changed to make the request side work and now no longer equals the SP's entity ID; several environments (test, production) share one IdP application.
- Diagnose: compare Audience with the SP entity ID and Recipient with the external ACS URL; check the SP's base URL or forwarded header settings.
- Fix: configure the SP with its external URL and keep one IdP application per environment.
Assertion not yet valid or expired
- Symptom: intermittent failures with "not yet valid" or "expired", often on one server in a pool.
- Likely causes: SP host clock drift; the user took too long on a step-up prompt and the assertion window passed; a saved bookmark replays an old POST.
- Diagnose: compare IssueInstant, NotBefore and NotOnOrAfter with the SP server time in the log entry. The python3-saml library, for example, allows 300 seconds of drift.
- Fix: repair time synchronisation on the SP host. Do not raise allowed drift beyond a few minutes.
InResponseTo mismatch or unsolicited response
- Symptom: failures after the user opened several tabs, used the back button, or started sign-in from an IdP portal tile.
- Likely causes: the SP keeps the AuthnRequest ID in a session cookie that was lost (SameSite rules, cookie on a different host, load balancer without session affinity); the SP does not accept IdP-initiated responses.
- Diagnose: check whether InResponseTo is present and whether the SP session still holds the request ID.
- Fix: store request state in a way that survives the cross-site POST, or enable IdP-initiated SSO deliberately with its replay protections, not by disabling InResponseTo checks.
User signs in but is not recognised or has no rights
- Symptom: "user not found", a new empty account, or missing roles in the application.
- Likely causes: NameID set to an attribute the SP does not use (object ID instead of email or UPN), a NameID Format mismatch, a UPN change after rename or marriage, the user not provisioned in the app, or a role or group claim not configured.
- Diagnose: read NameID and the AttributeStatement in the decoded assertion and compare with the SP account record.
- Fix: choose a stable, unique identifier for NameID, add the missing claims, and provision users before first sign-in. See the SCIM Provisioning Errors Troubleshooting Guide.
Authentication context not met
- Symptom: NoAuthnContext from the IdP, or Entra AADSTS75011: "The authentication method by which the user authenticated with the service doesn't match requested authentication method."
- Cause and fix: the SP hard-codes a RequestedAuthnContext such as password protected transport while the user signed in with a passkey, certificate or federated method. Remove or broaden the requested context at the SP and enforce strength through IdP policy instead.
Signing certificate rollover without an outage
Microsoft Entra ID creates SAML signing certificates valid for three years and emails up to five notification addresses 60, 30 and 7 days before expiry. Other IdPs follow similar patterns. A safe rollover:
- Add owned group mailboxes, not individuals, as notification addresses for every SAML application.
- Create the new certificate at the IdP; it stays inactive.
- Check whether the SP supports two trusted certificates or a metadata URL. Microsoft advises application vendors to support multiple certificates and refresh metadata at least every 24 hours.
- If it does, add the new certificate at the SP first, then make it active at the IdP. If it holds only one, agree a short change window and switch both sides together.
- Test sign-in immediately, keep the old certificate available for rollback until the test passes, then remove it from the SP.
Note Microsoft's warning: if an SP does not validate certificate expiry, an expired certificate matching on both sides keeps working, so an apparently healthy app can fail the moment a new certificate is activated.
Decision guidance
| Decision | Option A | Option B | Choose A when |
|---|---|---|---|
| Configuration exchange | Metadata URL, refreshed automatically | Manual certificate and URL entry | The SP supports it; it removes most rollover outages |
| SSO initiation | SP-initiated only | Also allow IdP-initiated | Security matters more than portal convenience; SP-initiated binds the response to a request |
| NameID | Persistent or immutable identifier | Email or UPN | Users are renamed often; choose B only when the SP cannot store an opaque ID |
| Signing scope | Sign response and assertion | Sign assertion only | The SP validates both; otherwise match what the SP verifies |
| Legacy SHA-1 app | Replace or upgrade the SP | Per-app SHA-1 exception | Always plan A; B only with an owner and an end date |
A small organisation with a few dozen SAML apps can track certificates and owners in a spreadsheet. A large one needs an inventory of every federated application with owner, entity ID, certificate expiry and metadata method, fed from the IdP's API, and alerts at 60 days.
Detection and measurement
- IdP sign-in logs: failure codes per application, especially sudden spikes after a change or on certificate expiry dates.
- SP validation logs: forward them centrally. Repeated signature or audience failures from one source can indicate tampering attempts, not only misconfiguration.
- Federation changes: alert on new or modified signing certificates and federation trusts at the IdP; an unexpected certificate is the core of Golden SAML (MITRE ATT&CK T1606.002). See the Golden SAML and Federation Trust Abuse Defence Guide.
Metrics:
- SAML sign-in failure rate per application, weekly.
- Number of signing certificates expiring within 60 days without a scheduled change.
- Share of SAML apps using metadata URLs rather than manual configuration.
- Share of SAML apps with a named owner and group notification address.
- Count of apps with SHA-1 or validation exceptions (target: falling to zero).
- Mean time to resolve SAML incidents.
Framework mapping
| Area | Reference | Relevance |
|---|---|---|
| Authentication of users and services | NIST CSF 2.0 PR.AA-03; NIST SP 800-53 IA-2, IA-8 | Federated authentication for organisational and external users |
| Credential management | NIST CSF 2.0 PR.AA-01 | Signing certificates and federation trust lifecycle |
| Session authenticity | NIST SP 800-53 SC-23 | InResponseTo, audience and recipient checks bind assertions to sessions |
| Log review | NIST SP 800-53 AU-6 | IdP and SP failure analysis |
| Secure authentication | ISO/IEC 27001:2022 A.8.5 | Signed, time bound assertions |
| Adversary technique | MITRE ATT&CK T1606.002 SAML Tokens | Forged assertions after signing key theft |
Common failure patterns
- Disabling signature validation to "get it working": the SP then accepts any assertion, including a forged one.
- Personal mailbox as the only certificate contact: the person leaves and the 60, 30 and 7 day notices go nowhere.
- Treating the signing key as configuration rather than a credential: the token signing key is a machine credential of the highest value; its theft enabled forged SAML tokens in the SolarWinds supply chain compromise.
- Editing the IdP Identifier to match a broken SP request: the request side starts working and the audience check on the response fails.
- Email as NameID with no plan for renames: a changed address creates a duplicate account or locks the user out.
- Pasting assertions into public decoders: a valid assertion is a bearer credential until NotOnOrAfter.
Practitioner checklist
- Establish which side rejected the exchange before changing any setting.
- Capture the SAMLRequest, SAMLResponse, correlation ID and timestamp for every incident.
- Decode locally and compare Issuer, ACS URL, Destination, Audience, Recipient, NameID and certificate with configuration.
- Read the SP library log for the exact validation message.
- Check SP host time before touching clock tolerance.
- Use metadata URLs where supported and keep one IdP application per environment.
- Give every SAML app an owner and a group notification address; review expiries monthly.
- Record exceptions (SHA-1, IdP-initiated) with an owner and an end date.
Standards and references
- OASIS: Assertions and Protocols for the OASIS Security Assertion Markup Language (SAML) V2.0
- Microsoft Learn: Microsoft Entra authentication and authorization error codes
- Microsoft Learn: Debug SAML-based single sign-on to applications
- Microsoft Learn: An app page shows an error message after the user signs in
- Microsoft Learn: Manage certificates for federated single sign-on
- SAML-Toolkits: python3-saml library
Related NHI Mgmt Group resources: SAML Security Guide · Golden SAML and Federation Trust Abuse Defence Guide · SAML to OIDC Migration · Federation and Trust Relationships Guide · Kerberos Error Codes Troubleshooting Guide