livery_client_dpop (livery v0.13.0)

View Source

DPoP proofs for outbound requests (RFC 9449, client side).

A DPoP-bound token is useless on its own: every request that carries it also carries a proof, a short JWT signed with a key only this client holds, naming the method and URL of that request. livery_client_oauth uses this module when you pass it dpop; you only call it directly to send proofs from your own layer.

new/2 makes a context: the signing key, its public JWK and its thumbprint (RFC 7638), which the authorization server puts in the token's cnf.jkt. A key you pass with key => {Alg, PrivateKey} is used as is. Without one, an ES256 key is generated the first time a Scope is seen and shared by every context of that scope on this node, so rebuilding a client does not change the key, and the cached tokens stay usable. That key lives in memory only: after a restart a new one is made and new tokens are fetched for it.

proof/4 signs a proof for a method and URL, with ath when it goes with an access token. htu is the URL without query and fragment (section 4.2). The server may ask for a nonce (section 8 and 9): the last DPoP-Nonce a server sent is kept per key and origin, and put in the next proof to that origin.

Summary

Functions

A DPoP context from Opts (#{key => {Alg, PrivateKey}}, or #{} for a generated ES256 key shared by every context made with Scope).

A proof for Method on Url, bound to AccessToken (or undefined at the token endpoint), with the last nonce the origin of Url sent.

Keep the DPoP-Nonce of a response from Url, if it has one.

Send Req with Send, adding a proof when livery_client_oauth put a DPoP token in its meta, and keeping the nonce of the answer. Called by livery_client once the URL is final.

The ETS table of generated keys and nonces, created by livery_client_token_store.

The RFC 7638 thumbprint of the context's key.

Types

ctx()

-opaque ctx()

Functions

new(Scope, Opts)

-spec new(term(), map()) -> ctx().

A DPoP context from Opts (#{key => {Alg, PrivateKey}}, or #{} for a generated ES256 key shared by every context made with Scope).

proof/4

-spec proof(ctx(), atom() | binary(), binary(), binary() | undefined) -> binary().

A proof for Method on Url, bound to AccessToken (or undefined at the token endpoint), with the last nonce the origin of Url sent.

remember/3

-spec remember(ctx(), binary(), [{binary(), binary()}]) -> ok.

Keep the DPoP-Nonce of a response from Url, if it has one.

send/2

-spec send(livery_client:request(), fun((livery_client:request()) -> Result)) -> Result
              when Result :: {ok, livery_client:response()} | {error, term()}.

Send Req with Send, adding a proof when livery_client_oauth put a DPoP token in its meta, and keeping the nonce of the answer. Called by livery_client once the URL is final.

table()

-spec table() -> atom().

The ETS table of generated keys and nonces, created by livery_client_token_store.

thumbprint/1

-spec thumbprint(ctx()) -> binary().

The RFC 7638 thumbprint of the context's key.