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
| Binding | Where you see it | Encoding |
|---|---|---|
| HTTP-POST | Form field SAMLResponse (sometimes SAMLRequest) in a POST to the ACS URL | base64 of the XML |
| HTTP-Redirect | Query 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
| Field | Where | What breaks when it is wrong |
|---|---|---|
StatusCode | samlp:Status | Anything other than Success means the IdP refused. The second-level code (RequestDenied, InvalidNameIDPolicy, NoAuthnContext) says why. |
Destination | Response root | Must equal the URL it was posted to (the ACS URL). |
Issuer | Response and Assertion | Must equal the IdP entity ID the SP trusts. |
Audience | Conditions/AudienceRestriction | Must equal the SP entity ID. See audience mismatch. |
NotBefore / NotOnOrAfter | Conditions, SubjectConfirmationData | Outside the window = "not yet valid" or "expired" - usually clock skew between IdP and SP. |
InResponseTo | Response, SubjectConfirmationData | Must match the AuthnRequest ID in SP-initiated flows. |
Recipient | SubjectConfirmationData | Must equal the ACS URL. |
NameID + Format | Subject | Who signed in; the SP may require a specific format. |
ds:Signature | Response and/or Assertion | Absent, SHA-1, or signed with a certificate the SP doesn't have = rejected. |
EncryptedAssertion | Response | Only the SP can decrypt it; you won't see attributes or conditions. |