AttestoClient.Token (AttestoClient v2.9.0)

Copy Markdown View Source

Refresh and revoke OAuth tokens.

Network operations are deadline-bound and are never retried because a timeout can leave the remote outcome unknown. Refresh-token rotation is available through refresh/4, which uses AttestoClient.RefreshCoordinator to prevent concurrent reuse for the same application record.

Returned tokens are not persisted by this library. Applications must perform any compare-and-swap update and choose their own token/session retention policy.

Summary

Functions

Exchange an OID4VCI pre-authorized code for an access token (urn:ietf:params:oauth:grant-type:pre-authorized_code, OpenID4VCI 1.0 Final §6.1/§6.2) - the wallet-holder token step ahead of AttestoClient.Wallet.request_credential/3.

Refresh a token set through a single-flight coordinator.

Revoke a token according to RFC 7009.

Functions

exchange_pre_authorized_code(pre_authorized_code, opts)

@spec exchange_pre_authorized_code(
  String.t(),
  keyword()
) :: {:ok, AttestoClient.TokenSet.t()} | {:error, term()}

Exchange an OID4VCI pre-authorized code for an access token (urn:ietf:params:oauth:grant-type:pre-authorized_code, OpenID4VCI 1.0 Final §6.1/§6.2) - the wallet-holder token step ahead of AttestoClient.Wallet.request_credential/3.

Required option: :token_endpoint. Private-key JWT authentication also uses :issuer from trusted discovery when supplied. An omitted issuer retains the deprecated endpoint-audience fallback in 2.x. :client_id may be omitted only with client_auth: :none, as permitted for anonymous pre-authorized-code flows; authenticated methods still require it. :client_auth and :req_options otherwise behave as for refresh/4. :alg, :kid, and :now configure DPoP proofs when :dpop is supplied. Pass :tx_code when the offer's grant carried a tx_code object, i.e. the end user must key in the transaction code the issuer displayed out of band.

Returns {:ok, token_set}; the ID Token, if any, is returned unverified since OID4VCI defines no binding claims for it here.

refresh(coordinator, key, tokens, opts)

@spec refresh(GenServer.server(), term(), AttestoClient.TokenSet.t(), keyword()) ::
  {:ok, AttestoClient.RefreshResult.t()} | {:error, term()}

Refresh a token set through a single-flight coordinator.

Required options are :token_endpoint, :issuer, :client_id, and the :subject from the previously verified ID Token; :client_auth and :req_options match AttestoClient.AuthorizationCode.callback/3. The issuer is validated before the request so an ID Token returned with a rotated refresh token can always be verified rather than losing the rotation result after the response.

:client_auth also accepts {:private_key_jwt, jwk, assertion_opts} for an explicitly registered assertion algorithm, key id, audience, lifetime, time, or JWT id.

A prior DPoP token set requires :dpop signing material before any network request. Persisted tokens.dpop_jkt must match that key; a missing or changed key is rejected locally. A requested or prior DPoP token cannot accept a Bearer response. Shared results are also checked against each caller's key before adoption. Legacy token sets without a thumbprint require a key, but their historical key continuity cannot be checked; a successful DPoP response records the supplied key for subsequent refreshes.

:alg, :kid, and :now configure each DPoP proof and are retained across the one permitted nonce retry.

The locally retained tokens.id_token_alg selects the ID Token verification algorithm. An explicit :id_token_alg must match it; mismatches fail before HTTP. The algorithm survives refreshes even when the response omits an ID Token, and shared results must match each caller's policy. Legacy token sets without this field use the explicit option or the existing default (PS256 for FAPI, RS256 otherwise), then retain that selection for subsequent refreshes.

revoke(token, opts)

@spec revoke(
  String.t(),
  keyword()
) :: :ok | {:error, term()}

Revoke a token according to RFC 7009.

A successful 2xx response is :ok, including when the server did not know the token. Required options: :revocation_endpoint, :client_id; optional :token_type_hint, :client_auth, :req_options, and :timeout. With private_key_jwt, pass :issuer from trusted discovery, or an explicit registered audience in the assertion options for a legacy server. Omitting both retains the deprecated endpoint-audience fallback in 2.x.