# `Attesto.LogoutToken`
[🔗](https://github.com/XukuLLC/attesto/blob/v0.13.0/lib/attesto/logout_token.ex#L1)

Mint OpenID Connect Back-Channel Logout `logout_token`s
(OpenID Connect Back-Channel Logout 1.0 §2.4).

A logout token is the signed JWT an OP POSTs to a Relying Party's
`backchannel_logout_uri` to tell it a session has ended. It is a distinct
artifact from the `Attesto.IDToken` and `Attesto.Token` this library also
mints: its JOSE header `typ` is the dedicated `logout+jwt` (so an RP can
reject anything else presented at its logout endpoint), and it carries an
`events` claim naming the back-channel-logout event rather than identity
or authorization claims.

Like `Attesto.IDToken`, minting is pure: it reads only the `Attesto.Config`
passed in, signs through the same keystore/`kid`/RS256 path, and funnels the
JOSE call through the shared internal JWS signer so the alg whitelist lives in
one place.

## Claims (Back-Channel Logout 1.0 §2.4)

Every minted logout token carries:

  * `iss` - the configured issuer.
  * `aud` - the OAuth `client_id` of the Relying Party (as in an ID Token).
  * `iat` - issued-at, unix seconds.
  * `jti` - a unique identifier, so an RP can detect a replayed token.
  * `events` - a JSON object with the single member
    `"http://schemas.openid.net/event/backchannel-logout"` mapped to an
    empty object, identifying this as a back-channel logout request.

At least one of:

  * `sub` - the subject whose session(s) ended.
  * `sid` - the session id that ended (the same value that rode in the ID
    Token's `sid` claim).

Per §2.4 a logout token **MUST NOT** contain a `nonce` claim; this module
never emits one. An `exp` is included with a deliberately short lifetime so
a captured token cannot be replayed indefinitely (the spec leaves `exp`
optional; including a short one is strictly safer for a conforming RP).

## Targeting `sub` vs `sid`

Back-Channel Logout 1.0 §2.4 requires a logout token to identify the
session by `sub`, `sid`, or both, and an RP advertises via
`backchannel_logout_session_required` whether it needs `sid`. Supply both
when known; supply `:sid` for an RP that requires session-scoped logout and
`:sub` for one that logs out every session for the subject.

# `mint_error`

```elixir
@type mint_error() :: :invalid_client_id | :missing_subject_identifier
```

# `mint_opts`

```elixir
@type mint_opts() :: [
  sub: String.t(),
  sid: String.t(),
  now: DateTime.t() | non_neg_integer(),
  lifetime: pos_integer(),
  jti: String.t()
]
```

# `event_uri`

```elixir
@spec event_uri() :: String.t()
```

The back-channel-logout `events` URI (Back-Channel Logout 1.0 §2.4).

# `header_typ`

```elixir
@spec header_typ() :: String.t()
```

The JOSE header `typ` logout tokens carry: `"logout+jwt"`.

# `mint`

```elixir
@spec mint(Attesto.Config.t(), String.t(), mint_opts()) ::
  {:ok, String.t()} | {:error, mint_error()}
```

Mint a signed Back-Channel Logout token addressed to the Relying Party
identified by `client_id` (which becomes `aud`, as in an ID Token).

Options:

  * `:sub` - the subject whose session ended.
  * `:sid` - the session id that ended (matches the ID Token `sid`).
    At least one of `:sub` / `:sid` MUST be supplied
    (`:missing_subject_identifier` otherwise).
  * `:jti` - override the generated unique identifier (a fresh CSPRNG value
    is used otherwise).
  * `:now` - `DateTime` or unix-seconds clock override. Defaults to now.
  * `:lifetime` - positive seconds; may only *shorten* the short default.

Returns `{:ok, logout_token}` (compact JWS) or `{:error, reason}`.

---

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