AuthTrace › Guides

How to decode a SAMLResponse

A SAMLResponse is an XML document that has been encoded so it can travel through the browser. How it is encoded depends on the binding, and you need to know which one you have before you can read it.

The two bindings

BindingWhere you see itEncoding
HTTP-POSTForm field SAMLResponse (sometimes SAMLRequest) in a POST to the ACS URLbase64 of the XML
HTTP-RedirectQuery parameter SAMLRequest or SAMLResponse in a GET (usually the AuthnRequest)raw DEFLATE, then base64, then URL-encoding

Responses almost always use POST (they are too big for a URL). AuthnRequests usually use Redirect. Redirect messages may also carry SigAlg and Signature parameters: the signature is over the query string, not inside the XML.

Decode a POST SAMLResponse by hand

Copy the value of the SAMLResponse form field (DevTools › Network › the POST to your ACS URL › Payload). If it is still URL-encoded (contains %2B or %3D), URL-decode it first.

# macOS / Linux
pbpaste | base64 --decode | xmllint --format -

# PowerShell
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String((Get-Clipboard)))

Decode a Redirect SAMLRequest by hand

Redirect values are compressed with raw DEFLATE (no zlib header), which most command-line tools don't handle directly. Python does:

python3 -c "import base64,zlib,sys,urllib.parse; v=urllib.parse.unquote(sys.argv[1]); print(zlib.decompress(base64.b64decode(v), -15).decode())" 'fZJNT8Mw...'

The -15 tells zlib to expect raw DEFLATE. If you get "incorrect header check", the value wasn't compressed - try plain base64.

Or skip all that

Open DevTools, pick the AuthTrace panel and sign in: every SAML message is decoded automatically, with the binding detected. For a value someone pasted into a ticket, click Decode in the panel and paste it - base64, deflated, URL-encoded, or a whole URL. Nothing leaves your browser.

What to read in the decoded response

FieldWhereWhat breaks when it is wrong
StatusCodesamlp:StatusAnything other than Success means the IdP refused. The second-level code (RequestDenied, InvalidNameIDPolicy, NoAuthnContext) says why.
DestinationResponse rootMust equal the URL it was posted to (the ACS URL).
IssuerResponse and AssertionMust equal the IdP entity ID the SP trusts.
AudienceConditions/AudienceRestrictionMust equal the SP entity ID. See audience mismatch.
NotBefore / NotOnOrAfterConditions, SubjectConfirmationDataOutside the window = "not yet valid" or "expired" - usually clock skew between IdP and SP.
InResponseToResponse, SubjectConfirmationDataMust match the AuthnRequest ID in SP-initiated flows.
RecipientSubjectConfirmationDataMust equal the ACS URL.
NameID + FormatSubjectWho signed in; the SP may require a specific format.
ds:SignatureResponse and/or AssertionAbsent, SHA-1, or signed with a certificate the SP doesn't have = rejected.
EncryptedAssertionResponseOnly the SP can decrypt it; you won't see attributes or conditions.
Handle decoded responses with care: they contain the user's identity and are valid credentials until they expire. AuthTrace Pro exports a redacted copy (NameID and emails masked, signature values cut) that is safe to attach to a ticket.