Validate an OpenID Connect RP-Initiated Logout request (OpenID Connect RP-Initiated Logout 1.0 §2-3).
The end-session endpoint is where a Relying Party sends the End-User's
browser to log out at the OP. Like the rest of attesto core this module is
pure — it parses and validates the request parameters and never touches a
store, a session, or a Plug.Conn. The host's controller owns loading the
client, terminating the browser session, and (for Back-Channel Logout)
fanning logout tokens out to the RPs.
Two steps, because the second needs data the controller must fetch in between:
parse/2validates the request parameters, verifies theid_token_hint(tolerating expiry — seeAttesto.IDToken.verify_logout_hint/2), and resolves the Relying Partyclient_idand the session identifiers (sub/sid) the back-channel fan-out will key on. It returns at/0the controller uses to load the client's registeredpost_logout_redirect_uris.confirm_redirect/2checks the requestedpost_logout_redirect_uriagainst that registered list (exact string match, RP-Initiated Logout §2/§3 — no normalization, no prefix matching) and returns the final redirect target withstateappended, or:no_redirectwhen the RP asked for none.
Resolving the client before validating the redirect URI is what makes an
open-redirect impossible: a post_logout_redirect_uri is only ever honored
when it exactly matches a value the client registered.
Summary
Functions
Confirm the request's post_logout_redirect_uri against the Relying Party's
registered list and compute the final redirect target.
Parse and validate the end-session request params (string- or atom-keyed).
Types
@type parse_error() :: :invalid_id_token_hint | :client_id_mismatch
@type t() :: %Attesto.EndSession{ client_id: String.t() | nil, logout_hint: String.t() | nil, post_logout_redirect_uri: String.t() | nil, sid: String.t() | nil, state: String.t() | nil, subject: String.t() | nil, ui_locales: String.t() | nil }
A parsed, hint-verified end-session request.
:client_id- the Relying Party, resolved from theid_token_hint'saudand/or theclient_idparameter (nil when the request carried neither, in which case nopost_logout_redirect_urican be honored).:subject/:sid- the session identifiers from theid_token_hint(nil when no hint was supplied); the keys a Back-Channel Logout fan-out uses to find the RP sessions to notify.:post_logout_redirect_uri/:state- the requested return target and opaque state, echoed back only after the URI is confirmed registered.:logout_hint/:ui_locales- passthrough hints (RP-Initiated Logout §2) for the host's logout-confirmation UI.
Functions
@spec confirm_redirect(t(), [String.t()]) :: {:ok, String.t() | :no_redirect} | {:error, :invalid_post_logout_redirect_uri}
Confirm the request's post_logout_redirect_uri against the Relying Party's
registered list and compute the final redirect target.
registered_uris is the client's registered post_logout_redirect_uris
(the host loads them from its Attesto.ClientStore between parse/2 and
this call). Matching is exact-string (RP-Initiated Logout §2/§3).
Returns:
{:ok, :no_redirect}- the request asked for no return URI; the host should render its own logged-out page.{:ok, url}- the validatedpost_logout_redirect_uriwith the request'sstateappended as a query parameter when present.{:error, :invalid_post_logout_redirect_uri}- the requested URI is not registered (or the RP could not be identified), so it MUST NOT be used.
@spec parse(Attesto.Config.t(), map()) :: {:ok, t()} | {:error, parse_error()}
Parse and validate the end-session request params (string- or atom-keyed).
Recognized parameters (OpenID Connect RP-Initiated Logout 1.0 §2):
id_token_hint, client_id, post_logout_redirect_uri, state,
logout_hint, ui_locales.
When id_token_hint is present it is verified via
Attesto.IDToken.verify_logout_hint/2 (signature + issuer, expiry
tolerated); a hint that fails verification is :invalid_id_token_hint. The
Relying Party client_id is taken from the hint's aud; if the client_id
parameter is also present it MUST equal it (:client_id_mismatch,
RP-Initiated Logout §2). With no hint, the client_id parameter alone
identifies the RP.
Returns {:ok, %Attesto.EndSession{}} or {:error, reason}.