feat(core): JWK Thumbprint URI (RFC 9278) - #733
Merged
Conversation
RFC 9278 names a key by its RFC 7638 thumbprint:
"urn:ietf:params:oauth:jwk-thumbprint:<hash-alg>:<thumbprint>". It is
the key-based "sub" or "kid" of OAuth DPoP, SIOP v2, OpenID for
Verifiable Credentials and OpenID Federation, and every implementer of
those profiles had to build and parse it by hand.
JwkThumbprintUri is the value object: fromKey(), parse(), matches() and
the accessors. It carries the mapping between the IANA "Named
Information Hash Algorithm" names the URI uses ("sha-256") and the
names PHP gives to the same functions ("sha256"), so that neither side
has to know it. Only the registered names PHP can compute are accepted;
truncated variants, BLAKE2, KangarooTwelve and non-registered names
("md5", "sha256") are refused with UnsupportedAlgorithmException. The
RFC 7638 computation is not duplicated: it goes through
JWK::thumbprint(), so the AKP case of #723 will flow through.
JWK::thumbprintUri() produces the URI and
JWKSet::selectKeyByThumbprintUri() is the verifier-side lookup. It is a
dedicated method rather than a restriction of selectKey(): the URI is
not a member of the key, and selectKey() compares members. As in
selectKey(), a key whose thumbprint cannot be computed is skipped.
key:thumbprint gains a "--uri" option. "--hash" then takes the IANA
name, and the PHP names of the supported functions are translated so
that the existing default "sha256" keeps working in both modes.
Closes #725
Spomky
added a commit
to web-token/jwt-doc
that referenced
this pull request
Sep 13, 2026
web-token/jwt-framework#733 adds JwkThumbprintUri, JWK::thumbprintUri(), JWKSet::selectKeyByThumbprintUri() and the "--uri" option of key:thumbprint. The key page gains a "Thumbprint URI" section with the IANA hash names, the key set page the lookup, the console page the option with a verified example; RFC 9278 joins the feature lists and the 4.2 → 4.3 guide.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #725
What
RFC 9278 names a key by its RFC 7638 thumbprint:
urn:ietf:params:oauth:jwk-thumbprint:<hash-alg>:<thumbprint>. It is the key-basedsub/kidof OAuth DPoP, SIOP v2, OpenID for Verifiable Credentials and OpenID Federation.Jose\Component\Core\JwkThumbprintUri—final readonlyvalue object:fromKey(JWK, $hashAlgorithm = 'sha-256'),parse($uri),isValid($uri),hashAlgorithms(),hashAlgorithm(),thumbprint(),matches(JWK)(constant-time),toString()/__toString(). It carries the IANA → PHP hash-name mapping (sha-256,sha-384,sha-512,sha3-224,sha3-256,sha3-384,sha3-512). Any other name —md5, the PHP spellingsha256, the truncatedsha-256-128,blake2b-256that PHP cannot compute — throwsUnsupportedAlgorithmException; a malformed URI throwsInvalidArgumentException.JWK::thumbprintUri(string $hashAlgorithm = 'sha-256'): string. The RFC 7638 computation is not duplicated: it callsthumbprint(), so the AKP case of feat(signature): ML-DSA-44/65/87 and the AKP key type via OpenSSL 3.5 (RFC 9964) #723 flows through.JWKSet::selectKeyByThumbprintUri(string|JwkThumbprintUri $uri): ?JWK— verifier-side lookup. A dedicated method rather than aselectKey()restriction, since the URI is not a key member andselectKey()compares members. A key whose thumbprint cannot be computed is skipped, asselectKey()does with malformed keys.key:thumbprint --uri—--hashthen takes the IANA name; the PHP names of the supported functions are translated so the existing defaultsha256works in both modes.Acceptance criteria
sha-256) →urn:ietf:params:oauth:jwk-thumbprint:sha-256:NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs✔sha-512andsha3-256URIs produced and parsed (values pinned in the tests);md5and unknown names refused ✔JWKSetlookup returns the matching key,nullotherwise ✔Tests
tests/Component/Core/JwkThumbprintUriTest.php(41 tests) and 7 newkey:thumbprintcases intests/Component/Console/KeyConversionCommandTest.php. PHPUnit, ECS, PHPStan (no baseline change), Rector and Deptrac are green.Out of scope
DPoP / SIOP / OID4VC logic, and what
thumbprint()hashes (#723).Documentation: web-token/jwt-doc.