Attesto.Plug.Authenticate (Attesto v0.5.0)

Copy Markdown View Source

Authenticate a protected-resource request: verify the access token and, for a DPoP-bound or mTLS-bound token, the sender-constraint proof.

A thin wrapper over the pure verifiers (Attesto.Token, Attesto.DPoP, Attesto.MTLS). It does the HTTP-specific work - parsing the Authorization and DPoP headers, building the htu, computing the client-certificate thumbprint via a host callback, wiring the replay and nonce checks - then delegates every decision to the engine and assigns the verified claims onto the conn.

Options

  • :config (required) - an Attesto.Config or a zero-arity function returning one.

  • :replay_check - the DPoP :replay_check callback ((jti, ttl) -> :ok | {:error, :replay}), e.g. &Attesto.DPoP.ReplayCache.check_and_record/2. Required for DPoP: without it, RFC 9449 §11.1 replay rejection is off and a captured proof can be replayed within the iat window. This plug therefore fails closed - a DPoP request is rejected (401 invalid_dpop_proof, replay_check_unconfigured) unless :replay_check is wired, so an unprotected DPoP endpoint cannot silently ship. Bearer/mTLS requests are unaffected. A host that knowingly accepts unprotected DPoP sets dpop_replay_unprotected_acknowledged?: true to opt out.

  • :dpop_replay_unprotected_acknowledged? - set to true to allow DPoP requests through WITHOUT :replay_check, accepting that captured proofs are replayable. Off by default (fail closed).

  • :nonce_check - the DPoP :nonce_check callback ((nonce | nil) -> :ok | {:error, :use_dpop_nonce}).

  • :nonce_issue - a zero-arity function returning a fresh DPoP nonce for the use_dpop_nonce challenge (required if :nonce_check is set), e.g. &Attesto.DPoP.NonceStore.ETS.issue/0.

  • :cert_der - (conn -> der_binary | nil); the DER of the client certificate the TLS layer authenticated. TLS termination varies, so the host supplies it. When it returns a certificate, its RFC 8705 thumbprint is handed to Attesto.Token.verify/3.

  • :htu - (conn -> https_uri_string) overriding how the request URI (without query/fragment) is built; default uses conn directly, which requires the scheme/host to reflect the external request (configure your proxy-forwarding rewrite).

  • :claims_key - the conn.assigns key the verified claims are put under (default :attesto_claims).

    plug Attesto.Plug.Authenticate, config: &MyApp.Attesto.config/0, replay_check: &MyApp.DPoPReplay.check_and_record/2, cert_der: &MyApp.TLS.client_cert_der/1