Diagnose SAML responses by status code
Every SAML 2.0 response carries a <Status> element whose StatusCode URI tells
you the outcome. The top-level code is one of Success, Requester, Responder
or VersionMismatch, and an optional nested second-level code explains the
specific reason — AuthnFailed, NoPassive, RequestDenied and so on. This tool
lists every standard code with its full URI, level and which party it blames, so
you can read a failed SSO response quickly.
The four top-level codes
Success (urn:oasis:names:tc:SAML:2.0:status:Success) means the protocol exchange completed without error. Important: this does not mean authentication succeeded. A Success response may still contain an assertion with a failed condition — always validate the assertion’s signature, its Conditions element (NotBefore, NotOnOrAfter), and the AudienceRestriction before trusting it.
Requester means the problem is with the request that the service provider (SP) sent. Common causes: malformed XML, an invalid NameID format requested, an unsupported binding, or a metadata mismatch between the SP and IdP. Fix this on the SP side.
Responder means the identity provider (IdP) encountered an error independent of whether the request was valid. Examples: backend authentication failure, database error, or a decision to deny the request on policy grounds. Fix this on the IdP side or check with your IdP’s admin.
VersionMismatch means the SP requested a SAML version that the IdP does not support. In practice this is rare because SAML 2.0 is universal; it usually indicates a misconfigured request or a very old implementation.
How the status element is structured
<samlp:Status>
<samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
<samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"/>
</samlp:StatusCode>
<samlp:StatusMessage>
User account locked out.
</samlp:StatusMessage>
</samlp:Status>
The outer StatusCode is the top-level verdict; the inner StatusCode is the second-level detail. The optional StatusMessage is free text from the IdP that often contains the most actionable information.
How it works
SAML status codes live under the urn:oasis:names:tc:SAML:2.0:status: namespace.
The first StatusCode is the top-level verdict. When more detail is needed, a
second-level StatusCode is nested inside the first. For example a top-level
Responder paired with a second-level AuthnFailed tells you the IdP ran fine but
could not authenticate the user.
Common second-level codes and what they mean
| Code | Top-level pairing | Meaning |
|---|---|---|
| AuthnFailed | Responder | IdP attempted but failed to authenticate the user |
| NoPassive | Responder | IsPassive=true requested but no session exists; retry with interaction |
| NoAuthnContext | Responder | IdP cannot satisfy the requested AuthnContext class |
| RequestDenied | Requester or Responder | SP or IdP policy denies the request |
| InvalidAttrNameOrValue | Requester | Attribute in the request is invalid |
| UnsupportedBinding | Requester | The requested binding (redirect/POST/artifact) is not supported |
| UnknownPrincipal | Responder | The requested principal (user) is unknown to the IdP |
| RequestVersionDeprecated | Requester | The requested SAML version is deprecated |
Tips
When debugging a broken SSO login, read the second-level code first — that is where the actionable detail lives. A Requester failure means fix your SP configuration (NameID policy, attributes, metadata endpoint). A Responder failure means look at the IdP logs. If you see NoPassive, retry without IsPassive=true. Always log the full <StatusMessage> string alongside the code — IdPs often put specific error messages there (user not found, account disabled, MFA required) that are not encoded in the standard codes.