Skip to content

feat: fallback to trying all JWKS keys when kid does not match#893

Open
liudonggalaxy wants to merge 1 commit into
authlib:mainfrom
liudonggalaxy:Dongliu/oidc_kid_mismatch_fallback_try_all_keys
Open

feat: fallback to trying all JWKS keys when kid does not match#893
liudonggalaxy wants to merge 1 commit into
authlib:mainfrom
liudonggalaxy:Dongliu/oidc_kid_mismatch_fallback_try_all_keys

Conversation

@liudonggalaxy

@liudonggalaxy liudonggalaxy commented May 15, 2026

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

This is a feature implementation that adds a configurable fallback for OIDC ID token verification when the token's kid header does not match any key in the provider's JWKS.

What is the current behavior?

When jwt.decode() raises InvalidKeyIdError, the code refreshes the JWKS and retries. If the kid still does not match after refresh, InvalidKeyIdError is raised with no way to recover. This breaks integration with OIDC providers whose JWKS keys lack a kid field or use kid values that do not match the token header.

What is the new behavior?

On InvalidKeyIdError:

  1. Refresh JWKS via fetch_jwk_set(force=True) to handle key rotation
  2. Retry kid-based decode with refreshed keyset
  3. If should_try_all_keys() returns True, try each key individually; otherwise re-raise InvalidKeyIdError (default, backwards-compatible)

Subclasses can override should_try_all_keys() to enable the brute-force fallback:

class MyOAuth(OAuth):
    def should_try_all_keys(self):
        return True

Checklist

  • The commits follow the conventional commits specification.
  • You ran the linters with prek.
  • You wrote unit test to demonstrate the bug you are fixing, or to stress the feature you are bringing.
  • You reached 100% of code coverage on the code you edited, without abusive use of pragma: no cover
  • If this PR is about a new feature, or a behavior change, you have updated the documentation accordingly.

  • You consent that the copyright of your pull request source code belongs to Authlib's author.

@liudonggalaxy liudonggalaxy force-pushed the Dongliu/oidc_kid_mismatch_fallback_try_all_keys branch from 7790b09 to 4482c61 Compare May 15, 2026 20:33
@liudonggalaxy liudonggalaxy changed the title Fallback to trying all JWKS keys when kid does not match feat: fallback to trying all JWKS keys when kid does not match May 15, 2026
@liudonggalaxy liudonggalaxy force-pushed the Dongliu/oidc_kid_mismatch_fallback_try_all_keys branch 7 times, most recently from 5835873 to a9c210a Compare May 16, 2026 00:06
Add a configurable fallback for OIDC ID token verification when the
token's kid header does not match any key in the provider's JWKS.

Behavior on InvalidKeyIdError:
1. Refresh JWKS via fetch_jwk_set(force=True) to handle key rotation
2. Retry kid-based decode with refreshed keyset
3. If should_try_all_keys() returns True, try each key individually;
   otherwise re-raise InvalidKeyIdError (default, backwards-compatible)

Co-authored-by: Copilot <[email protected]>
@liudonggalaxy liudonggalaxy force-pushed the Dongliu/oidc_kid_mismatch_fallback_try_all_keys branch from a9c210a to 4ee4def Compare May 16, 2026 00:19
@liudonggalaxy liudonggalaxy marked this pull request as ready for review May 16, 2026 00:37
@lepture

lepture commented May 19, 2026

Copy link
Copy Markdown
Member

Is there a real use case? I don't think it is a good idea go accept non-matched keys.

@liudonggalaxy

Copy link
Copy Markdown
Contributor Author

Is there a real use case? I don't think it is a good idea go accept non-matched keys.

Yes. Some identity providers do not include kid values in their JWKS responses. For example, Palantir’s Multipass JWKS endpoint may return keys like this:

{
    "keys": [
        {
            "kty": "EC",
            "crv": "P-256",
            "x": "t85AHwgZP8Sz_0Q0YZOr4kn4WxXrQeYa7OPDJwg2cnM",
            "y": "GHPmt7eNhuiffYymKabMppQwS-HipAbFyDuidZ5DoJ0"
        },
        {
            "kty": "EC",
            "crv": "P-256",
            "x": "cW__b1XeUUoXEzTMf7ty6rjy38HokQ7GGtMTL5ZC-1E",
            "y": "pLXB3SjRNZyTw8cQrF0mZQO7OjTASzrNOT0xsBKXZ-U"
        }
    ]
}

The mozilla-django-oidc library supports a similar OIDC_VERIFY_KID settings to disable kid check for JWKS keys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants