# `ExSaml.Core.Binding`
[🔗](https://github.com/docJerem/ex_saml/blob/main/lib/ex_saml/core/binding.ex#L1)

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).

| Step                        | Direction | Binding                            | Endpoint read from                               |
| --------------------------- | --------- | ---------------------------------- | ------------------------------------------------ |
| 1. `AuthnRequest`           | SP → IdP  | HTTP-Redirect **or** HTTP-POST     | IdP metadata — `<md:SingleSignOnService>`        |
| 2. `Response` + `Assertion` | IdP → SP  | HTTP-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`.

# `html_doc`

```elixir
@type html_doc() :: binary()
```

# `uri`

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

# `xml`

```elixir
@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()}
```

# `decode_response`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`
*macro* 

# `xmlDocument`
*macro* 

# `xmlElement`
*macro* 

# `xmlElement`
*macro* 

---

*Consult [api-reference.md](api-reference.md) for complete listing*
