Compact JWS signing and verification (RFC 7515) for the ATProto OAuth profile.
Only elliptic-curve algorithms are supported — the spec-required ES256
and the optional ES256K — because those are the only algorithms ATProto
allows for client assertions and DPoP proofs.
Examples
{:ok, jwk} = Exosphere.ATProto.OAuth.JWK.generate(:p256)
{:ok, jwt} = Exosphere.ATProto.OAuth.JWS.sign(jwk, %{"alg" => "ES256"}, %{"sub" => "did:plc:abc"})
{:ok, %{"sub" => "did:plc:abc"}} = Exosphere.ATProto.OAuth.JWS.verify(Exosphere.ATProto.OAuth.JWK.to_public(jwk), jwt, ["ES256"])
Summary
Functions
Decode a compact JWS without verifying it — for inspecting headers/claims
(e.g. the jwk header of an incoming DPoP proof) before verification.
Sign claims as a compact JWS (header.payload.signature).
Verify a compact JWS against a public JWK, restricting algs per RFC 8725
(explicit algorithm selection).
Types
Functions
Decode a compact JWS without verifying it — for inspecting headers/claims
(e.g. the jwk header of an incoming DPoP proof) before verification.
@spec sign(Exosphere.ATProto.OAuth.JWK.t(), map(), map()) :: {:ok, binary()} | {:error, term()}
Sign claims as a compact JWS (header.payload.signature).
headers must include "alg"; it overrides JOSE's defaults so that
non-standard JOSE headers (typ: dpop+jwt, jwk, …) round-trip.
@spec verify(Exosphere.ATProto.OAuth.JWK.t(), binary(), [String.t()]) :: {:ok, map()} | {:error, :invalid_signature | :invalid_token}
Verify a compact JWS against a public JWK, restricting algs per RFC 8725
(explicit algorithm selection).
Returns {:ok, claims} when the signature is valid.