Build the two JWTs of OAuth 2.0 Attestation-Based Client Authentication
(draft-ietf-oauth-attestation-based-client-auth-10), the client-side mirror
of Attesto.WalletAttestation.verify/3 and the client-auth method OID4VCI
recommends for native-app wallets over private_key_jwt/mTLS.
Two artifacts, signed by two different keys:
attestation/2- the Client Attestation JWT (typoauth-client-attestation+jwt), issued by the Wallet Provider (Client Attester) and signed by its key. It binds the wallet instance's public key intocnfand names the instance'sclient_idinsub. It is long-lived and reused across many requests; an:x5cheader lets the server chain the signer to a configured trust anchor.pop/2- the Client Attestation PoP JWT (typoauth-client-attestation-pop+jwt), minted fresh per request and signed by the instance key (the private half of the attestation'scnfkey), proving possession to oneaud(the server's identifier).
The client presents them in the OAuth-Client-Attestation and
OAuth-Client-Attestation-PoP headers; AttestoClient.OAuthHTTP's
{:client_attestation, ...} client-auth attaches both. Signing and key-bound
:alg/:kid validation behave as in AttestoClient.Wallet.Proof (shared
AttestoClient.Builder internals).
Summary
Functions
Build a Client Attestation JWT, returning {:ok, compact_jws} or
{:error, reason}. Fails fast on invalid input.
Build a Client Attestation PoP JWT, returning {:ok, compact_jws} or
{:error, reason}. Fails fast on invalid input.
Types
@type error() :: :invalid_key | :invalid_client_id | :invalid_audience | :invalid_instance_key | :invalid_lifetime | :invalid_jti | :unsupported_alg | :unsupported_key | {:signing_failed, String.t()}
@type jwk() :: JOSE.JWK.t() | map()
Functions
@spec attestation(jwk(), [attestation_opt()]) :: {:ok, String.t()} | {:error, error()}
Build a Client Attestation JWT, returning {:ok, compact_jws} or
{:error, reason}. Fails fast on invalid input.
provider_key is the Wallet Provider (Client Attester) private key that signs
the attestation. Required options:
:client_id- the wallet instance's client identifier (becomessub).:instance_key- the wallet instance's key; its public half is embedded as thecnfconfirmation JWK the PoP must be signed by.
Optional: :x5c (a list of base64 DER certificates for the x5c header, so
the server can chain the signer to a trust anchor), :lifetime (seconds to
exp, default 3600), and :alg,
:kid, :now as in AttestoClient.Wallet.Proof.build/2.
Build a Client Attestation PoP JWT, returning {:ok, compact_jws} or
{:error, reason}. Fails fast on invalid input.
instance_key is the wallet instance private key - the private half of the
attestation's cnf key. Required options:
:client_id- the wallet instance's client identifier (becomesiss).:audience- the server's identifier the PoP is presented to (aud); an AS issuer URL or a resource identifier, single-valued.
Optional: :challenge (echo a server-issued Challenge), :jti (default a
fresh random value), :lifetime (seconds to exp, default
120), and :alg, :kid, :now.