DPoP (RFC 9449) proof JWTs for the ATProto OAuth profile.
Every request an ATProto OAuth client makes — the PAR request, the token
requests, and each resource (XRPC) request — carries a fresh proof JWT in a
DPoP header, signed by the session's DPoP key, binding the request's
method and URI (and, for resource requests, the access token via ath).
Servers may require a server-issued nonce (400 with use_dpop_nonce and
a DPoP-Nonce response header); Exosphere.ATProto.OAuth.Request handles
the retry loop, backed by Exosphere.ATProto.OAuth.DPoP.NonceStore.
Examples
{:ok, key} = Exosphere.ATProto.OAuth.DPoP.generate_key()
proof = Exosphere.ATProto.OAuth.DPoP.proof(key, "POST", "https://pds.example.com/xrpc/com.atproto.repo.describeRepo",
ath: "eyJ...")
Summary
Functions
Generate a fresh P-256 DPoP keypair as a private JWK map.
Whether an error response is a DPoP nonce challenge that should be retried
(400 with error use_dpop_nonce, or 401 carrying a DPoP-Nonce
header) — and if so, the nonce to use.
Extract the DPoP-Nonce header from a response header list.
Normalize a URL into an htu per RFC 9449 §4.3: scheme and host
lowercased, default ports dropped (non-default ports kept), path retained
(empty becomes /), query and fragment stripped.
The origin (scheme://host[:port], default ports dropped) of a URL.
Mint a DPoP proof JWT for a request.
Types
@type private_key() :: Exosphere.ATProto.OAuth.JWK.t()
Functions
@spec generate_key() :: {:ok, private_key()}
Generate a fresh P-256 DPoP keypair as a private JWK map.
ATProto clients generate a new DPoP key per user/device/session, starting with the PAR request.
@spec nonce_challenge?(%{ status: pos_integer(), headers: [{String.t(), String.t()}], body: term() }) :: String.t() | nil
Whether an error response is a DPoP nonce challenge that should be retried
(400 with error use_dpop_nonce, or 401 carrying a DPoP-Nonce
header) — and if so, the nonce to use.
Extract the DPoP-Nonce header from a response header list.
Normalize a URL into an htu per RFC 9449 §4.3: scheme and host
lowercased, default ports dropped (non-default ports kept), path retained
(empty becomes /), query and fragment stripped.
The origin (scheme://host[:port], default ports dropped) of a URL.
Used as the key for per-authorization-server nonce tracking.
Mint a DPoP proof JWT for a request.
Options
:nonce- server-issued nonce (required when the server has issued one):ath- access token; when present, its SHA-256 hash is bound into the proof asath(resource-server requests):iat- issuance time in seconds (defaults to now); for tests