ExSaml.Core.Binding (ex_saml v1.1.0)

Copy Markdown View Source

SAML HTTP binding handlers.

Pure Elixir port of the Erlang esaml_binding module. Provides encoding/decoding of SAML messages for HTTP-Redirect and HTTP-POST bindings.

Binding direction in the Web Browser SSO profile

A SAML Web Browser SSO flow is asymmetric: the binding used to send the AuthnRequest (SP → IdP) is independent of the binding used to deliver the Response (IdP → SP).

StepDirectionBindingEndpoint read from
1. AuthnRequestSP → IdPHTTP-Redirect or HTTP-POSTIdP metadata — <md:SingleSignOnService>
2. Response + AssertionIdP → SPHTTP-POST (or Artifact / PAOS)SP metadata — <md:AssertionConsumerService>

What is commonly referred to as the "HTTP-Redirect binding flow" only concerns step 1 — it is how the SP transports the AuthnRequest (DEFLATE compressed, base64-encoded, placed in an URL query string, triggered via a 302 Location:). In ex_saml this is controlled per IdP by the use_redirect_for_req option.

Step 2 is always HTTP-POST in practice, regardless of how the request was sent. SAML Responses embed a signed (and often encrypted) Assertion that easily reaches several KB, which cannot fit in a URL. The SAML specification forbids HTTP-Redirect for the AssertionConsumerService endpoint (SAML 2.0 Bindings §3.4.3, Profiles §4.1.3.5) for this reason.

Consequently, SP metadata generated by ex_saml advertises an AssertionConsumerService using HTTP-POST only — even when the provider is configured with use_redirect_for_req: true.

Summary

Functions

Unpack and parse a SAMLResponse with the given encoding.

Encode a SAMLRequest (or SAMLResponse) as an HTTP-POST binding.

Encode a SAMLRequest (or SAMLResponse) as an HTTP-POST binding with an optional nonce for the inline script tag.

Encode a SAMLRequest (or SAMLResponse) as an HTTP-Redirect binding.

Types

html_doc()

@type html_doc() :: binary()

uri()

@type uri() :: binary() | String.t()

xml()

@type xml() ::
  {:xmlElement, name :: term(), expanded_name :: term(), nsinfo :: term(),
   namespace :: term(), parents :: term(), pos :: term(), attributes :: term(),
   content :: term(), language :: term(), xmlbase :: term(),
   elementdef :: term()}
  | {:xmlDocument, content :: term()}

Functions

decode_response(arg1, saml_response)

@spec decode_response(binary(), binary()) :: xml()

Unpack and parse a SAMLResponse with the given encoding.

When the encoding is the DEFLATE URI, the response is base64-decoded then zlib-unzipped. For any other encoding the response is base64-decoded and an unzip is attempted, falling back to the raw decoded data if decompression fails. The resulting XML string is then parsed with :xmerl_scan.

encode_http_post(idp_target, signed_xml, relay_state)

@spec encode_http_post(
  idp_target :: uri(),
  signed_xml :: xml(),
  relay_state :: binary()
) :: html_doc()

Encode a SAMLRequest (or SAMLResponse) as an HTTP-POST binding.

Returns an HTML document containing a form and JavaScript to auto-submit it.

encode_http_post(idp_target, signed_xml, relay_state, nonce)

@spec encode_http_post(
  idp_target :: uri(),
  signed_xml :: xml(),
  relay_state :: binary(),
  nonce :: binary()
) :: html_doc()

Encode a SAMLRequest (or SAMLResponse) as an HTTP-POST binding with an optional nonce for the inline script tag.

Returns an HTML document containing a form and JavaScript to auto-submit it.

encode_http_redirect(idp_target, signed_xml, username, relay_state)

@spec encode_http_redirect(
  idp_target :: uri(),
  signed_xml :: xml(),
  username :: nil | binary(),
  relay_state :: binary()
) :: binary()

Encode a SAMLRequest (or SAMLResponse) as an HTTP-Redirect binding.

Returns the full redirect URI including query parameters for SAMLEncoding, the payload (as SAMLRequest or SAMLResponse depending on the XML root element), RelayState, and an optional username.

xmlDocument(args \\ [])

(macro)

xmlDocument(record, args)

(macro)

xmlElement(args \\ [])

(macro)

xmlElement(record, args)

(macro)