Skip to content

Proposal: Standardized JWKS cache fallback on refresh failure #348

@RoderK-Git

Description

@RoderK-Git

Context

MicroProfile JWT allows verification keys to be loaded from a remote JWKS endpoint via mp.jwt.verify.publickey.location. Implementations typically cache the JWKS and honor HTTP caching headers such as Cache-Control: max-age.

In real-world enterprise deployments, the JWKS endpoint may become temporarily unavailable due to network or service issues.

Motivation

If the cached JWKS expires and a refresh attempt fails, some implementations discard the cache immediately and reject subsequent authentications. This can cause a complete authentication outage even though a previously valid JWKS is still locally available.

Some implementations already provide vendor-specific mitigations, but this behavior is not standardized and therefore not portable.

Proposal

I would like to propose standardizing an optional JWKS cache fallback mechanism for remote JWKS retrieval failures, conceptually similar to HTTP stale-if-error semantics.

The idea is to allow continued use of the last successfully retrieved JWKS for a bounded, configurable grace period when refresh fails.

Proposed specification text

(draft)

X.Y Remote JWKS Retrieval and Cache Fallback

When mp.jwt.verify.publickey.location refers to an HTTP(S) URL, the MicroProfile JWT implementation retrieves a JSON Web Key Set (JWKS) from a remote endpoint and may cache the retrieved keys for subsequent token verification.

X.Y.1 JWKS caching and refresh

Implementations SHOULD cache a successfully retrieved JWKS and SHOULD respect HTTP caching headers (such as Cache-Control: max-age) provided by the JWKS endpoint when determining the normal cache lifetime.

When the cached JWKS reaches the end of its freshness lifetime, the implementation SHOULD attempt to refresh the JWKS by retrieving it again from the configured location.

X.Y.2 Handling refresh failures

If a refresh attempt of a remote JWKS fails (for example due to network errors, timeouts, non-success HTTP status codes, or parsing errors), the implementation MAY continue to use the last successfully retrieved JWKS for a bounded fallback period, instead of immediately rejecting token verification requests.

This behavior is conceptually similar to HTTP cache semantics such as stale-if-error, but is scoped specifically to JWKS handling for JWT verification.

X.Y.3 Configuration of fallback duration

The fallback behavior described above is controlled by a MicroProfile Config property:

mp.jwt.verify.jwks.retain-cache-on-error-duration
  • The value represents a duration (e.g. in seconds or minutes).
  • Default value: 0.
  • A value of 0 disables the fallback mechanism; in this case, implementations MUST fail token verification if the JWKS cannot be refreshed.
  • A value greater than 0 specifies the maximum duration for which a previously valid JWKS may be reused after a refresh failure.

Property naming and duration format follow standard MicroProfile Config conventions.

X.Y.4 Configuration precedence

The mp.jwt.verify.jwks.retain-cache-on-error-duration property follows standard MicroProfile Config source precedence rules.

In case multiple configuration sources are present, the effective value is determined according to MicroProfile Config ordering, allowing:

  1. application-level configuration to override,
  2. runtime / server / domain-level configuration to provide defaults,
  3. implementation defaults to apply when no configuration is specified.

This enables centralized governance in enterprise environments while preserving application portability.

X.Y.5 Security considerations

Reusing a previously valid JWKS during a refresh failure may delay the effect of key rotation while the remote JWKS endpoint is unavailable.
Implementations and operators are expected to mitigate this risk by:

keeping fallback durations short,

disabling the fallback entirely if strict behavior is required.

Notes

This proposal is intended to improve operational resilience while keeping security trade-offs explicit and bounded via configuration.

Happy to refine naming, wording, or scope based on feedback.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions