skip to content

Bindings and Profiles

How messages travel: an auto-submitting form POST versus a deflated, base64 query string, plus the Web Browser SSO profile. Binding choice explains most URL-length and signature failures.

part ofFederated identityoverview, primer and where to startread it →
on this pageshow

questions

4

Why does the SAML HTTP-POST binding show the user a page that submits itself, and what is on that form?

level: juniorimportance: must knowfreq 52%

answer

  1. browsers cannot POST on their own
  2. a page whose only job is submitting
  3. hidden control, name fixed by the binding
  4. base64 of the XML, no compression
  5. SAMLResponse plus an optional RelayState

basics

~20 s

A browser will not originate a cross-site POST on its own, so the sender returns a page holding a form aimed at the recipient's endpoint and submits it by script. The form carries the base64-encoded SAML message in a hidden control named SAMLRequest or SAMLResponse.

solid answer

~40 s

The HTTP-POST binding, `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`, has to get a message from one server to another through a browser that only follows redirects and submits forms. Since there is no way to ask a browser to POST somewhere by itself, the sender returns an ordinary page whose form `action` is the recipient's endpoint, `method` is POST, and whose hidden control is named exactly `SAMLRequest` or `SAMLResponse` with the base64-encoded XML as its value. An optional second hidden control named `RelayState` may ride along, capped at 80 bytes by the binding. A script submits the form on load, and a `noscript` button lets the user do it manually. The flash of a near-empty page is that form being posted.

code

xml · 6 lines
xml
<form method="POST" action="https://register.example/sso/acs">
  <input type="hidden" name="SAMLResponse"
         value="PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6..."/>
  <input type="hidden" name="RelayState" value="drw-4417-rev14"/>
  <noscript><input type="submit" value="Continue"/></noscript>
</form>

go deeper

for a junior

Recall the shape: a page arrives, a hidden field named SAMLRequest or SAMLResponse holds base64 XML, and a script posts the form to the other party's endpoint. That is the whole mechanism.

for a middle

Explain why the binding exists at all — a browser will not originate a cross-site POST — and name what the binding fixes: the control names, the base64 encoding with no compression, and the optional 80-byte RelayState control.

for a senior

Show you can debug it from the wire: a mistyped control name, a GET where a POST was expected, base64 whitespace that one binding tolerates and the other forbids, and a resubmitted form arriving twice.

for a principal

The judgment call is which binding each message direction uses across a set of partners, and what you standardise on when their length limits and encoders differ. Uniformity is worth more here than per-partner optimisation.

## What a binding is, and what this one has to solve A SAML **binding** is the rule for putting a SAML protocol message onto a concrete transport. It is neither the message nor the profile. The **Web Browser SSO profile**, `urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser`, says which messages flow between which parties; a binding says how each one physically travels. That profile has an awkward constraint at its centre: the two servers exchanging messages frequently have no direct connection to each other, so every message rides in the user's browser. A browser is a cooperative courier with exactly two habits a server can rely on. It follows a redirect by itself, and it submits a form. What it will never do is originate a cross-site POST unprompted. The HTTP-POST binding, `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`, is built on the second habit: to make the browser POST a message to the recipient's endpoint, the sender returns an ordinary HTML page containing a form aimed at that endpoint plus a small script that submits it on load. The blank flash the user sees — often captioned "please wait" — is that page. ## What is actually on the page - The form's `action` is the recipient's endpoint URL and its `method` is `POST`. - One hidden control is named **exactly** `SAMLRequest` when a request is being sent, or `SAMLResponse` when a response is. These names are fixed by the binding; they are not a local convention, and they are case-sensitive. - That control's value is the **base64 encoding (RFC 2045) of the XML message**. No compression is applied — this is the single largest mechanical difference from the Redirect binding. - If the sender is carrying state through the round trip, a second hidden control named `RelayState` holds it. At the binding level its value must not exceed **80 bytes**; what it means and who is allowed to trust it is a different subject entirely. - A `noscript` submit button, so the exchange still completes where scripting is off. The browser then sends an ordinary `application/x-www-form-urlencoded` POST body containing those same parameter names. ## POST against Redirect, on the points that matter here | | HTTP-POST | HTTP-Redirect | |---|---|---| | Encoding of the message | base64 of the XML | DEFLATE, then base64, then URL-encoding | | Where the message sits | a form control in a POST body | a query-string parameter | | Practical length budget | effectively none | whatever the shortest intermediary allows | | How a signature travels | enveloped inside the XML, untouched by the binding | detached, as separate `SigAlg` and `Signature` query parameters | | What the user sees | a page that submits itself | a redirect, with no visible page | ## Why a response almost always arrives this way A `<Response>` carrying a signed assertion is a large document, and the parts that make it large — a signature value, an embedded certificate — are high-entropy, so they barely compress. After encoding, such a message essentially precludes the Redirect binding on length grounds alone, which is why the binding specification prefers POST where a message contains signed content. There is a second, quieter reason. On this binding the sender does not have to do anything about signing at all: an enveloped XML signature sits inside the XML and is carried inside the base64 blob unchanged, so the binding neither knows nor cares that it is there. The Redirect binding cannot do that and must define a separate, detached signature over the query string instead. ## What goes wrong, and how it looks 1. **A mistyped control name.** `samlResponse`, `SAML_Response` or `saml-response` do not exist. The recipient sees a POST with no SAML parameter in it and rejects the whole request as malformed, which reads to an operator like "the identity provider sent nothing". 2. **The wrong binding aimed at the endpoint.** If the endpoint receives a GET whose query string carries `SAMLResponse`, the sender used HTTP-Redirect against an endpoint that expects HTTP-POST. Nothing about the message is wrong; the transport is. 3. **Base64 line breaks.** RFC 2045 base64 permits line breaks, and most POST-side parsers tolerate them. On the Redirect binding whitespace must be removed, so a sender that reuses one encoder for both bindings can work on one and fail on the other. 4. **The back button and resubmission.** Because the page really did submit a form, going back can prompt the user to resubmit it, and the recipient may then receive the same message twice. Deciding what to do with a repeat is the receiving implementation's problem, not the binding's. The habit worth forming is to read the exchange as bytes: which parameter name, which encoding, which HTTP method. Almost every binding-level failure is visible in exactly those three facts.

  • What happens if the hidden control is named samlResponse instead of SAMLResponse?
    The recipient looks for `SAMLRequest` or `SAMLResponse` and finds neither, so it sees a POST with no SAML message in it and rejects the request. The names are fixed by the binding and case-sensitive; there is no fallback matching.
  • Why does this binding not compress the message the way HTTP-Redirect does?
    Compression exists on the Redirect binding to fight a URL length ceiling. A POST body has no comparable practical limit, so compressing would buy nothing but processing cost and one more place for two implementations to disagree.
  • What does the user see if scripting is disabled in the browser?
    The page stops at the form instead of submitting it, and the `noscript` button — conventionally labelled something like "Continue" — lets the user post it manually. The exchange still completes; it simply needs one click.

saying these in an interview costs you the question

  • Says the POST binding compresses the message like Redirect does
  • Thinks the hidden control can be named whatever the sender likes
  • Believes base64 in the form hides the message from the user
  • Calls the self-submitting page an implementation quirk rather than the binding
  • Treats a GET carrying SAMLResponse as the same binding
open as a page

What encodings does the SAML HTTP-Redirect binding apply to a message, and why does the result still overflow URLs?

level: middleimportance: must knowfreq 46%

basics

~20 s

The message is DEFLATE-compressed, then base64-encoded, then URL-encoded into a SAMLRequest or SAMLResponse query parameter. Base64 adds about a third back and percent-encoding adds more, so anything carrying a signature and a certificate barely compresses and overflows.

open as a page

On the SAML HTTP-Redirect binding, which octets do SigAlg and Signature cover, and why does re-encoding the parsed message break verification?

level: seniorimportance: should knowfreq 35%

basics

~10 s

They cover a query string built in the fixed order SAMLRequest=value&RelayState=value&SigAlg=value, with the values URL-encoded exactly as sent. Neither DEFLATE nor percent-encoding is canonical, so a rebuilt string is different octets and fails.

open as a page

What does the SAMLart value in the SAML HTTP-Artifact binding contain, and how is the real message fetched?

level: middleimportance: nice to knowfreq 22%

basics

~20 s

SAMLart carries a short base64 reference, not the message: a TypeCode, an EndpointIndex, a 20-byte SourceID and a 20-byte MessageHandle. The recipient redeems it by sending ArtifactResolve to the issuer over a back channel and receiving ArtifactResponse.

open as a page