[OID4VCI]: Fix JWT proof JWK claim type confusion causing proof validation failure#50822
Open
Awambeng wants to merge 2 commits into
Open
[OID4VCI]: Fix JWT proof JWK claim type confusion causing proof validation failure#50822Awambeng wants to merge 2 commits into
Awambeng wants to merge 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Updates JWK claim handling to avoid type-confusion casts during OID4VCI proof validation.
Changes:
- Returns
nullfor mismatched JWK claim types. - Adds unit and OID4VCI regression tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
core/src/main/java/org/keycloak/jose/jwk/JWK.java |
Handles claim type mismatches. |
core/src/test/java/org/keycloak/jose/jwk/JWKOtherClaimTest.java |
Tests typed claim retrieval. |
services/src/test/java/org/keycloak/protocol/oid4vc/issuance/keybinding/JwtProofValidatorTest.java |
Adds malformed-proof coverage. |
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRefreshInTab1Keycloak CI - Forms IT (chrome) org.keycloak.testsuite.forms.MultipleTabsLoginTest#testEmptyBaseUrlKeycloak CI - Forms IT (firefox) |
This was referenced Jul 22, 2026
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRegisterClickKeycloak CI - Forms IT (chrome) org.keycloak.testsuite.forms.MultipleTabsLoginTest#testEmptyBaseUrlKeycloak CI - Forms IT (firefox) |
- Make JWK.getOtherClaim() type-safe by catching ClassCastException and returning null on type mismatch - Add JWKOtherClaimTest with 5 tests verifying type-safe getOtherClaim behavior - Add regression test in JwtProofValidatorTest for malformed JWK crv in proof header Closes keycloak#50749 Signed-off-by: Awambeng Rodrick <awambengrodrick@gmail.com>
Signed-off-by: Awambeng Rodrick <awambengrodrick@gmail.com>
This was referenced Jul 27, 2026
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.
Issue
"crv": [](an array instead of a string) in the JOSE headerjwkfield could trigger an unhandledClassCastExceptioninAbstractProofValidator.getKeyWrapper(), resulting in a 500 Internal Server Error instead of the expectedinvalid_proofresponse.Root cause
JWK.getOtherClaim("crv", String.class)internally callsString.class.cast(ArrayList), which throws aClassCastExceptionwhen the claim has an unexpected type. This exception was not handled byJwtProofValidator.validateProof(), whose catch block only handledJWSInputException,VerificationException, andIOException.Fix
JWK.getOtherClaim()(root cause): Now catchesClassCastExceptionand returnsnull. A type mismatch is treated the same as a missing claim, matching the method's contract. This provides a systemic fix for all callers, includingAbstractProofValidator,JWKSUtils, andEdECUtilsImpl.AbstractProofValidator.getKeyWrapper()(defense in depth): WrapsJWKParser.toPublicKey()in atry-catch(RuntimeException)and rethrows aVerificationException. This ensures malformed JWKs (for example, missingktyor required EC fields) follow the existingINVALID_PROOFerror path instead of propagating unchecked exceptions.Why not catch
RuntimeException?RuntimeExceptioninJwtProofValidatorwas intentionally avoided becauseVCIssuerExceptionextendsRuntimeException. Doing so would incorrectly convert issuer-specific errors (for example,INVALID_NONCE) into genericINVALID_PROOFresponses.Tests
JWKOtherClaimTest: 5 unit tests covering valid retrieval, absent claim, wrong type returningnull,nullvalue, and correct type retrieval.OID4VCJWTIssuerEndpointTest.testRequestCredentialWithMalformedJwkCrvRejected(): Integration test verifying that a malformed"crv": []JWT proof returns 400INVALID_PROOFinstead of causing an internal server error.Closes #50749