Latch.DPoP (latch v0.4.0)

Copy Markdown

DPoP (RFC 9449) proof JWTs for atproto OAuth, and server-issued nonce flow shared by Latch.XRPC and Latch.Flow.

Summary

Functions

S256 hash of an access token for the ath claim (same as PKCE S256)

Generates a new ES256 (P-256) key pair as a plain RFC 7517 JWK map.

Extract dpop-nonce header from a map of headers.

Signs a DPoP proof JWT for an HTTP request.

RFC 7638 thumbprint of a plain JWK map.

Plumbing for the DPoP-nonce flow used in Latch.Flow and Latch.XRPC. This wraps the logic for getting nonces, caching new ones, and retrying challenges like 4xx responses.

Types

send_error()

send_result()

@type send_result() ::
  {{:ok, map()} | :challenge | {:error, send_error()}, String.t() | nil}

Functions

access_token_hash(access_token)

@spec access_token_hash(String.t()) :: String.t()

S256 hash of an access token for the ath claim (same as PKCE S256)

generate_key()

@spec generate_key() :: map()

Generates a new ES256 (P-256) key pair as a plain RFC 7517 JWK map.

nonce_header(headers)

@spec nonce_header(map()) :: String.t() | nil

Extract dpop-nonce header from a map of headers.

proof(key_map, method, url, opts \\ [])

@spec proof(map(), String.t(), String.t(), keyword()) :: String.t()

Signs a DPoP proof JWT for an HTTP request.

Arguments

  • jwk — private plain JWK map for this OAuth session
  • method — HTTP method (e.g. "POST")
  • url — request URL; query string is stripped for htu per atproto

Options

  • :nonce — server DPoP nonce (omit when unknown)
  • :access_token — adds ath (S256 hash) for PDS/resource requests
  • :jti — override jti (tests)
  • :iat — override iat (tests) Note: atproto currently says do not include iss on PDS-bound proofs.

thumbprint(key_map)

@spec thumbprint(map()) :: String.t()

RFC 7638 thumbprint of a plain JWK map.

with_nonce(config, dpop_key, url, send)

@spec with_nonce(Latch.Config.t(), map(), String.t(), (String.t() | nil ->
                                                   send_result())) ::
  {:ok, map()} | {:error, Latch.Error.MissingDPoPNonce.t() | send_error()}

Plumbing for the DPoP-nonce flow used in Latch.Flow and Latch.XRPC. This wraps the logic for getting nonces, caching new ones, and retrying challenges like 4xx responses.