feat: add cacheMaxAgeFallback option for graceful JWKS degradation during outages#502
Open
cschetan77 wants to merge 1 commit into
Open
feat: add cacheMaxAgeFallback option for graceful JWKS degradation during outages#502cschetan77 wants to merge 1 commit into
cschetan77 wants to merge 1 commit into
Conversation
…resilient when JWKS endpoint is down and cache for kid has expired
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.
Description
When the JWKS endpoint is unavailable and the cache for a kid has expired, the library currently hard-evicts the key and begins rejecting all tokens — causing a full service outage even for tokens that remain valid.
This PR introduces a cacheMaxAgeFallback option: a second TTL that defines how long beyond cacheMaxAge the library will continue serving a stale cached key when the AS is unreachable.
Changes
src/wrappers/cache.js: wraps the memoizer's load function with stale fallback logic, maintains a bounded LRUCache (same max as main cache) for stale entries.index.d.ts: addscacheMaxAgeFallback?:number toOptionsBasepackage.json: addslru-cache ^11.0.0as a direct dependency (was previously only a transitive dep via lru-memoizer)Working
cacheMaxAge) is unchanged.Date.now() - lastFetchedAt < cacheMaxAge + cacheMaxAgeFallback.cacheMaxAgeFallbackis undefined by default, opt-in only, no change to existing behavior.Security consideration
This is an explicit availability vs. security tradeoff. In a key compromise scenario where the AS rotates keys and goes briefly unreachable simultaneously, stale keys would continue to be trusted for the duration of the fallback window. For this reason, cacheMaxAgeFallback has no default, the callers must set it consciously based on their threat model and expected AS recovery.