Attesto.AuthorizationRequest (Attesto v0.6.13)

Copy Markdown View Source

Authorization endpoint request validation (RFC 6749 §4.1.1, OIDC Core §3.1.2.1, RFC 7636 §4.3).

This module validates the protocol shape of an authorization request that the transport layer has already parsed out of the query string. It checks the response_type, the presence of client_id and redirect_uri, the requested scope (surfacing whether the OpenID Connect openid scope was requested), and the PKCE parameters (code_challenge + code_challenge_method). It carries state, nonce, claims, and the optional prompt / max_age / acr_values parameters through to the normalized result.

It deliberately does NOT:

  • authenticate the resource owner or render consent (host policy, performed in the Phoenix layer);
  • decide whether the client_id exists, beyond requiring it to be present;
  • issue an authorization code (Attesto.AuthorizationCode.issue/3 does that, consuming the normalized request this module returns).

It DOES check redirect_uri against the registered set the caller passes in :registered_redirect_uris by exact string match (RFC 6749 §3.1.2.3, OIDC Core §3.1.2.1): the registered set is a fact the host supplies, not a policy decision this module makes.

Error disposition (OIDC Core §3.1.2.6, RFC 6749 §4.1.2.1)

RFC 6749 §4.1.2.1 and OIDC Core §3.1.2.6 split authorization errors into two classes by where the error may be reported:

  • {:error, {:direct, reason}} - the request client_id or redirect_uri is missing or invalid. The authorization server MUST NOT redirect back to the supplied URI (it is untrusted); the error is shown directly to the user agent. Reasons: :invalid_client_id, :missing_redirect_uri, :invalid_redirect_uri, :redirect_uri_not_registered.

  • {:error, {:redirect, error}} - the client_id/redirect_uri pair is trusted but some other parameter is invalid. The server redirects back to the validated redirect_uri with an error (and error_description) query parameter, echoing state when present. The error map carries: :error (the RFC 6749 §4.1.2.1 code), :error_description, :redirect_uri, and :state.

The Phoenix layer turns each class into the correct HTTP response; this core module only classifies.

Summary

Types

The classification of a validation failure (OIDC Core §3.1.2.6).

A redirectable authorization error (RFC 6749 §4.1.2.1).

t()

A normalized, validated authorization request.

Functions

The response modes this authorization-code server accepts (OAuth 2.0 Response Modes / JARM §2.3): query and the JARM JWT modes. Exposed so the discovery document advertises exactly what validate/2 enforces.

Validate a parsed authorization request parameter map (RFC 6749 §4.1.1, OIDC Core §3.1.2.1, RFC 7636 §4.3).

Types

error()

@type error() ::
  {:direct,
   :invalid_client_id
   | :missing_redirect_uri
   | :invalid_redirect_uri
   | :redirect_uri_not_registered}
  | {:redirect, redirect_error()}

The classification of a validation failure (OIDC Core §3.1.2.6).

redirect_error()

@type redirect_error() :: %{
  :error => String.t(),
  :error_description => String.t(),
  :redirect_uri => String.t(),
  :state => String.t() | nil,
  optional(:response_mode) => String.t() | nil,
  optional(:client_id) => String.t()
}

A redirectable authorization error (RFC 6749 §4.1.2.1).

Errors raised once the client is trusted (from validate_redirectable/5) also carry :response_mode (the requested JARM mode, or nil) and :client_id, so the transport can return the error in the requested response mode (JARM §2.3); earlier errors omit them.

t()

@type t() :: %Attesto.AuthorizationRequest{
  acr_values: [String.t()],
  claims: map(),
  client_id: String.t(),
  code_challenge: String.t() | nil,
  code_challenge_method: String.t() | nil,
  max_age: non_neg_integer() | nil,
  nonce: String.t() | nil,
  openid?: boolean(),
  prompt: [String.t()],
  redirect_uri: String.t(),
  response_mode: String.t() | nil,
  response_type: String.t(),
  scope: [String.t()],
  state: String.t() | nil
}

A normalized, validated authorization request.

The binding fields (client_id, redirect_uri, scope, code_challenge, code_challenge_method, nonce) line up with the attrs Attesto.AuthorizationCode.issue/3 consumes.

Functions

supported_response_modes()

@spec supported_response_modes() :: [String.t()]

The response modes this authorization-code server accepts (OAuth 2.0 Response Modes / JARM §2.3): query and the JARM JWT modes. Exposed so the discovery document advertises exactly what validate/2 enforces.

validate(params, opts)

@spec validate(
  map(),
  keyword()
) :: {:ok, t()} | {:error, error()}

Validate a parsed authorization request parameter map (RFC 6749 §4.1.1, OIDC Core §3.1.2.1, RFC 7636 §4.3).

params is a string-keyed map of the authorization request query parameters.

Options

  • :registered_redirect_uris (required) - the list of redirect URIs registered for the client. The request redirect_uri MUST be an exact string match against one of these (RFC 6749 §3.1.2.3, OIDC Core §3.1.2.1). An empty list rejects every request with {:direct, :redirect_uri_not_registered}.

  • :require_nonce (optional, default false) - the host's OP nonce policy. When true, an OpenID Connect Authentication Request (one whose EFFECTIVE scope - after any signed request object is merged - carries openid) with no nonce is rejected with a redirectable invalid_request error (OIDC Core §3.1.2.1). The openid test runs on the merged request, so a scope=openid carried only inside a signed request object still triggers the requirement. A plain OAuth request (no openid scope) is never nonce-constrained (RFC 6749 keeps code at SHOULD). When false, nonce stays OPTIONAL and is carried through unenforced.

  • :require_pkce (optional, default true) - when true, a request with no code_challenge is rejected with a redirectable invalid_request error (RFC 7636 §4.3). When false, an absent code_challenge is permitted and the validated request carries none. The caller MUST pass false only for a confidential client: RFC 9700 §2.1.1 keeps PKCE a MUST for public clients. A code_challenge that IS present is fully enforced (S256, no plain) regardless of this flag - presence means the client opted into PKCE, so a downgrade is always rejected.

  • :request_object_policy (optional, default %Attesto.RequestObject.Policy{})

Returns {:ok, %Attesto.AuthorizationRequest{}} or {:error, error()}, where error() is classified per the moduledoc.

The client_id / redirect_uri checks run first, because their failure is non-redirectable (OIDC Core §3.1.2.6): only once a trusted redirect_uri is established may any further error be reported by redirecting to it.