added basic provisioner refresh on jwks cache miss - #2769
Draft
APWHY wants to merge 1 commit into
Draft
Conversation
APWHY
force-pushed
the
jwks-reload-on-unknown-kid
branch
from
August 25, 2026 07:30
e89a5d5 to
37eb0e8
Compare
keyStore only refetched the JWK Set once the cached set had expired, and that expiry comes from the endpoint's Cache-Control max-age. An identity provider that advertises a long max-age and rotates its signing key mid-window therefore made every token it issued fail to validate until the cache expired. An Amazon EKS OIDC issuer serves max-age=604800, so a rotation there breaks validation for up to seven days, recoverable only by restarting the CA. Reload when a key id is missing from the cached set, as OpenID Connect Core 10.1.1 recommends. A minimum interval between reloads bounds a sequential stream of key ids that no reload can resolve, and coalescing bounds a concurrent burst, as androidCRLCache already does in this package. The Cache-Control handling is left in place, so the expiry stays a proactive refresh rather than the only trigger. The GCP, Azure and OIDC provisioners all share this key store, so all three are affected. Also reject a JWKs response carrying an error status code. Such a response decoded into an empty key set without an error whenever its body was valid JSON, and reload then installed that in place of a usable key set; reloading on an unknown key id makes the path far more reachable. Reload failures are now logged rather than discarded, so a JWKs endpoint that has become unreachable is visible. The expiry now observes the same minimum interval as an unknown key id, because it is only advanced by a reload that succeeded: an expired key set and a failing endpoint otherwise reload, and so log, on every token. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
APWHY
force-pushed
the
jwks-reload-on-unknown-kid
branch
from
August 25, 2026 15:31
37eb0e8 to
8afa09b
Compare
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.
step-caonly refetches the JWKS from the issuer once the cached set has expired (which comes from the JWKS endpoint'sCache-Control: max-age). This means if the issuer rotates keys all future requests through the affected provisioners will fail until the cache expires naturally.This PR adds a refresh mechanism that runs at most once every minute if there is an unfamiliar received
kid, following the recommendation at: https://openid.net/specs/openid-connect-core-1_0.html#RotateSigKeys . Concurrent reload requests are grouped as well.go-oidchas done something similar where they've completely removed theCache-controlchecks entirely, but I wanted to minimise the changes this PR made so I've left them in for now.An additional fix has been added to
getKeysFromJWKsURIso it rejects non 2xx/3xx codes and returns an error. Previously, if the error had a decodeable JSON body it would attempt to do so and empty the keystore (and error out otherwise). It's not entirely related and I can split this out into a separate PR if needed.