AttestoPhoenix.AuthorizationServer.RequestPolicy (AttestoPhoenix v0.9.0)

Copy Markdown View Source

Conn-free resolution of the per-request authorization-request validation policy shared by the authorization endpoint and the PAR endpoint.

Both endpoints validate the same authorization request the same way (RFC 9126 §2.1: "validate the pushed request as it would an authorization request sent to the authorization endpoint"), so the policy inputs Attesto.AuthorizationRequest.validate/2 needs - the client's registered redirect URIs (RFC 6749 §3.1.2.3), whether PKCE is required (RFC 9700 §2.1.1), and whether nonce is required (OIDC Core §3.1.2.1) - are resolved here once, from %AttestoPhoenix.Config{} and the opaque host client, rather than duplicated per endpoint. This module reads only data: it touches no conn and carries no policy of its own beyond the fail-closed defaults documented on each function.

Summary

Functions

Classify the client as public via the host's :client_public? callback.

The client's registered redirect URIs (RFC 6749 §3.1.2.3).

The host's OP nonce policy flag (OIDC Core §3.1.2.1).

Whether PKCE is required for this client (RFC 7636 §4.3 / RFC 9700 §2.1.1).

Validate params as an authorization request for client, resolving the redirect-URI/PKCE/nonce policy from config and delegating to Attesto.AuthorizationRequest.validate/2.

Functions

client_public?(config, client)

@spec client_public?(AttestoPhoenix.Config.t(), term()) :: boolean()

Classify the client as public via the host's :client_public? callback.

Absent the callback, fail closed by treating the client as public, so PKCE stays required (a confidential exemption demands a deliberate host classification).

registered_redirect_uris(config, client)

@spec registered_redirect_uris(AttestoPhoenix.Config.t(), term()) :: [String.t()]

The client's registered redirect URIs (RFC 6749 §3.1.2.3).

For a CIMD client ({:cimd, metadata}, draft-ietf-oauth-client-id-metadata-document-01) the document is the registration, so the registered set is the document's own redirect_uris (RFC 9700) and the host's per-client callback is never consulted. For a registered client the set is resolved through the host's :client_redirect_uris callback; an absent callback or a non-list return resolves to [], which rejects every request with an unregistered redirect URI (fail closed).

require_nonce?(config)

@spec require_nonce?(AttestoPhoenix.Config.t()) :: boolean()

The host's OP nonce policy flag (OIDC Core §3.1.2.1).

Returns the raw :require_nonce configuration. The OIDC openid-scope gate is NOT applied here: it must run on the EFFECTIVE request (after any signed request object is merged), which only Attesto.AuthorizationRequest.validate/2 sees. Applying the gate on the raw outer params here would let a direct JAR carrying scope=openid only inside the signed object bypass the requirement.

require_pkce?(config, client)

@spec require_pkce?(AttestoPhoenix.Config.t(), term()) :: boolean()

Whether PKCE is required for this client (RFC 7636 §4.3 / RFC 9700 §2.1.1).

A public client MUST use PKCE, so client_public?/2 forces it regardless of config. A sender-constrained client (DPoP or mTLS) is a FAPI 2.0 client, and FAPI 2.0 Security Profile §5.3.1.2 / RFC 9700 §2.1.1 require PKCE for it even though it authenticates confidentially - so client_requires_dpop?/2 and client_requires_mtls?/2 force it too. For any other confidential client the global :require_pkce flag applies (default true). Fail closed: absent the host's deliberate opt-out, PKCE is required.

validate(config, client, params, extra_opts \\ [])

Validate params as an authorization request for client, resolving the redirect-URI/PKCE/nonce policy from config and delegating to Attesto.AuthorizationRequest.validate/2.

This is the shared entry point both the authorization endpoint and the PAR endpoint use so a request is validated identically wherever it arrives (RFC 9126 §2.1). Pass extra_opts to thread request-object verification inputs (:request_object_jwks, :request_object_audience, :request_object_policy) when the params still carry an unverified signed request object; omit them when the object has already been verified and merged.