Better support for OIDC JWK keys without kid #35529
Merged
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.
This PR is the last one to get the OIDC Basic RP test plan passing:
https://www.certification.openid.net/plan-detail.html?plan=RPUGzpD20SQYS&public=true
This PR improves how verification keys without
kid
property are handled.By default, the token includes a key identifier,
kid
header and it is used to find a matching JWK, example, if the tokenkid
is1
, then, given[{"kid":"1", "kty":"RSA", "alg":"RS256"}, {{"kid":"2", "kty":"RSA", "alg":"RS256"}]
, the key with the"kid":"1"
will be selected.There is a case (this was driven by a concrete user requirement), when the token does not include a key identifier (
kid
) property. Quarkus already supports verifying such tokens, but only (and this restriction was created without any specific justification) if the verification key set has a single JWK key only withoutkid
, for example:[{"kty":"RSA", "alg":"RS256"}]
- i.e, single key set only with this single key having nokid
.As it happens, the the OIDC Basic RP test plan tests this case too, but the verification key set contains more than one key without kid, with each key having its own key type, for example:
[{"kty":"RSA", "alg":"RS256"}, {{"kty":"EC", "alg":"ES256"}]
- i.e here 2 keys, one RSA, another EC, both withoutkid
are included, and the test is expected to get the token withoutkid
, signed with an RSA key, verified by the key with the matching key type, in this example, the first one, from the set.So this PR just makes sure that all the keys without
kid
(or X509 thumbprint) are keyed by their type, so when the token withoutkid
arrives, a single key with the matching key type is chosen.The test plan has another test, where more than one key without
kid
but with the same key type is available, for example:[{"kty":"RSA", "alg":"RS256"}, {{""kty":"RSA", "alg":"RS256"}]
- with 2 results supported - the first one, if the token has nokid
then Quarkus fails to verify it because more than one key withoutkid
with the matching RSA type is available; and the 2nd result is that Quarkus iterates over all such matching keys until the verification succeeds. I don't see the 2nd result being an option for us at the moment - it can take a lot of time to iterate over all such keys, the whole such scenario seems very much test-specific (not practical) so I chose the 1st option - fail to verify in this case - which matches the currentmain
expectations too.So to summarize, the only real improvement which this PR brings is it allows correctly identify a matching JWK without
kid
in a set containing more than one JWK, with each JWK having its own key type, with only JWK per specific key type possible.Tests added to
OidcProviderTest
to show it,integration-tests/oidc-wiremock
already has tests for the current case where a JWK set has a single key only