AttestoClient.AuthorizationCode (AttestoClient v2.2.0)

Copy Markdown View Source

OpenID Connect Authorization Code flow with S256 PKCE.

start/2 validates discovery metadata, creates high-entropy state, nonce, and PKCE values, stores the transaction with a finite lifetime, and returns the authorization URL. callback/3 atomically consumes state, exchanges the code exactly once, and verifies the ID Token against the stored issuer, client, nonce, configured algorithm, and returned access token.

Transactions are also bound to an opaque application-supplied browser-session value, preventing a response initiated in one user agent from being used in another. The store protects protocol correlation only. Applications remain responsible for deciding whether verified claims authorize a user, creating or retaining a session, and persisting rotated tokens.

Summary

Functions

Consume an authorization response and complete the code exchange.

Begin an authorization transaction.

Types

Functions

callback(store, params, opts \\ [])

@spec callback(store(), map(), keyword()) ::
  {:ok, %{tokens: AttestoClient.TokenSet.t(), id_token_claims: map()}}
  | {:error, term()}

Consume an authorization response and complete the code exchange.

params is the string-keyed callback parameter map. State is consumed before any token request, so replay and concurrent duplicate callbacks fail. :browser_binding is required and must equal the opaque value supplied to start/2; a mismatch consumes state and fails before token exchange. The client authentication option is forwarded as :client_auth; supported forms are :none, {:client_secret_basic, secret}, {:client_secret_post, secret}, and {:private_key_jwt, jwk}. The three-element form {:private_key_jwt, jwk, assertion_opts} accepts :alg, :kid, :audience, :lifetime, :now, and :jti for registrations whose client assertion differs from the defaults; :client_id is always pinned to the stored transaction.

A timeout leaves the remote outcome unknown and the transaction consumed; do not retry an authorization code.

start(store, opts)

@spec start(
  store(),
  keyword()
) ::
  {:ok, %{url: String.t(), state: String.t(), expires_in: pos_integer()}}
  | {:error, term()}

Begin an authorization transaction.

Required options are :issuer, :client_id, :redirect_uri, and an opaque :browser_binding retained in the initiating user agent's secure, HttpOnly application session. The same binding is mandatory at callback. The value is protocol correlation only; authorization and session policy remain application-owned.

Discovery is fetched unless :metadata is supplied. :scopes defaults to ["openid"] and must include openid. :id_token_alg defaults to "RS256" and must match the client's registration and the provider metadata.

Additional request values may be supplied in :authorization_params, but protocol-bound parameters cannot be overridden.