SIOPv2 Self-Issued ID Token verification for the Relying Party role.
A Self-Issued ID Token is not verified against an issuer-owned JWKS. The
holder either embeds a public key in sub_jwk and uses its RFC 7638 SHA-256
thumbprint as sub, or uses a self-contained did:jwk / did:key subject
whose resolved verification method signs the token. verify/2 ties the
subject, verification key, and signature together before returning the
verified subject and public key.
This module implements the JWK Thumbprint Subject Syntax Type from
Self-Issued OpenID Provider v2 draft 13, section 11.1. It accepts sub_jwk
in the payload, as the current draft specifies, and in the protected JOSE
header for wallet interoperability. If both locations are present, their
JWK maps must be identical.
The current draft identifies a Self-Issued ID Token with iss == sub.
https://self-issued.me/v2, used by the earlier static-discovery model, is
also accepted for JWK-thumbprint subjects. DID subjects require iss == sub
and a protected kid naming the method-defined verification method. Only
connection-free did:jwk and did:key are resolved here; network-backed DID
methods remain host-owned and fail closed.
Verification is conn-free and fail-closed:
- the compact JWS must be canonical and carry no unsupported critical headers;
algmust be an Attesto-supported asymmetric algorithm allowed by RP policy and compatible with a public verification JWK;- the signature must verify strictly with the embedded or DID-resolved holder key;
submust exactly equal the key's RFC 7638 thumbprint, or be thedid:jwk/did:keyfrom which the key and protectedkidare derived;issmust equalsubfor DID subjects, or eithersuborhttps://self-issued.me/v2for JWK-thumbprint subjects;audmust contain the RP Client ID andnoncemust exactly match the Authentication Request;expandiatare required non-negative NumericDates;nbfis optional but, when present, must also be a non-negative NumericDate. Expired and not-yet-valid tokens are rejected.
Claims other than the cryptographically bound sub remain self-attested.
Summary
Functions
Verify a Self-Issued ID Token and return its subject and holder public JWK.
Verify a Self-Issued ID Token against an RP Client ID and request nonce.
Types
@type verify_error() ::
:invalid_token
| :unsupported_critical_header
| :unexpected_typ
| :invalid_alg
| :missing_sub_jwk
| :invalid_sub_jwk
| :invalid_signature
| :invalid_subject
| :invalid_issuer
| :invalid_audience
| :invalid_nonce
| :invalid_claims
| :expired
| :not_yet_valid
@type verify_opts() :: [ audience: String.t(), nonce: String.t(), now: DateTime.t() | non_neg_integer(), accepted_algs: [Attesto.SigningAlg.alg()] ]
Functions
@spec verify(String.t(), verify_opts()) :: {:ok, verified()} | {:error, verify_error()}
Verify a Self-Issued ID Token and return its subject and holder public JWK.
JWK-thumbprint subjects may carry sub_jwk in the payload or protected
header. A did:jwk subject must instead carry protected kid equal to
did:jwk:...#0; a did:key subject must carry protected kid equal to the
DID followed by # and its multibase value. A DID response containing
sub_jwk, omitting kid, or naming any other verification method is
rejected.
Required options:
:audience- the RP Client ID sent in the Authentication Request. The token'saudmay be this string or an all-string array containing it.:nonce- the nonce sent in the Authentication Request. SIOPv2 requires it to be present and identical in the Self-Issued ID Token.
Optional options:
:now- clock reference as aDateTimeor Unix seconds.:accepted_algs- holder signature algorithms accepted by RP policy. Defaults toAttesto.SigningAlg.allowed/0;none, MAC algorithms, and algorithms unsupported by Attesto remain rejected even if listed.
The convenience verify/3 form accepts id_token, audience, and nonce
as positional arguments and applies the default clock and algorithm policy.
@spec verify(String.t(), String.t(), String.t()) :: {:ok, verified()} | {:error, verify_error()}
Verify a Self-Issued ID Token against an RP Client ID and request nonce.