How to decode a SAML message
- Paste what you have. All of these work:
- the bare
SAMLResponseorSAMLRequestvalue, URL-encoded or not SAMLRequest=…with or withoutRelayState,SigAlgandSignature- a whole Redirect URL copied from the address bar
- the HTML auto-submit form with the hidden
SAMLResponseinput - raw XML
- the bare
- The decoder detects the binding: plain Base64 means HTTP-POST, deflated data means HTTP-Redirect.
- Read the summary first, then the pretty-printed XML below it. The XML is shown as text and never rendered.
The Encode direction does the reverse: paste an AuthnRequest and get a Redirect value, a SAMLRequest= parameter or a full URL built from the Destination attribute. That is handy for replaying a request while testing a service provider.
Redirect binding vs POST binding
| HTTP-Redirect | HTTP-POST | |
|---|---|---|
| Transport | Query string of a GET request | Hidden form field, auto-submitted |
| Encoding | raw DEFLATE, then Base64, then URL encoding | Base64 only |
| Typical message | AuthnRequest, LogoutRequest | Response with assertions |
| Signature | Separate SigAlg and Signature parameters | XML signature inside the message |
| Recognizable by | no fixed prefix, binary after Base64 | PHNhbWxwOl (<samlp:), PHNhbWwycDp (<saml2p:), PD94bWwg (<?xml ) |
Redirect uses compression because URLs have practical length limits. In the example used on this page, a 464-character AuthnRequest deflates to 273 bytes and travels as 364 Base64 characters. Responses carry signatures and certificates, so they are too big for a URL and go through POST. The decoder also accepts zlib-wrapped data, which some service providers send on Redirect instead of raw deflate.
What to check when SSO fails
The summary pulls out the fields that cause most login failures:
- Status: anything other than
urn:oasis:names:tc:SAML:2.0:status:Success. A sub-code such asAuthnFailed,InvalidNameIDPolicyorRequestDeniednames the reason, andStatusMessageoften adds detail. - Destination and ACS URL: must match the endpoint configured at the service provider exactly, including
httpsand a trailing slash. - Audience: must equal the SP entity ID. A mismatch here is a common misconfiguration after renaming an application.
- Conditions:
NotBeforeandNotOnOrAfterare checked against your clock. “Expired” or “not valid yet” on a fresh login points to clock skew between the IdP and SP. - InResponseTo: should equal the
IDof theAuthnRequest. A mismatch suggests a stale or replayed response. The attribute is absent in IdP-initiated logins, which some service providers reject. - NameID and Format: the identifier the SP will match against its users, for example
emailAddressversuspersistent. - Attributes: every attribute with all its values, to confirm the IdP sends the groups or email the SP maps.
Decoding SAML in Python
import base64, zlib
from urllib.parse import unquote
def decode_post(value):
return base64.b64decode(value).decode()
def decode_redirect(value):
raw = base64.b64decode(unquote(value))
return zlib.decompress(raw, -15).decode()
The -15 tells zlib to expect raw deflate without a header. Call unquote only on values you copied from a URL; a value from a POST form is already plain Base64, and URL-decoding it can turn + into a space. More in Base64 in Python, and the compression side is explained on the raw deflate and zlib page.
Privacy of SAML assertions
An assertion holds names, email addresses, group memberships and sometimes more personal data, and a valid unexpired one can be a login token. This page decodes it locally and cannot send it anywhere. Still, redact assertions before pasting them into tickets or chats, and treat a captured response like a session cookie until its NotOnOrAfter has passed.
FAQ
How do I capture a SAML response in the browser?
Open the developer tools, enable Preserve log on the Network tab and sign in. Find the POST request to the service provider’s ACS URL and copy the SAMLResponse form field from its payload. Paste it here.
Why does my SAMLRequest not decode with a normal Base64 decoder?
With the HTTP-Redirect binding the XML is raw-deflate compressed before Base64 and URL encoding. A plain decoder shows binary noise. This tool URL-decodes, Base64-decodes and inflates in one go.
Does the decoder verify the SAML signature?
No. It reports whether the message, the assertion or the query string is signed, but it does not check the signature against the IdP certificate. Signature validation belongs in the service provider.
Can it decrypt an EncryptedAssertion?
No. Encrypted assertions need the service provider’s private key. The decoder counts them and still shows the unencrypted envelope: status, issuer and destination.