Interface JwksRefresher
- All Superinterfaces:
AutoCloseable, Closeable, io.confluent.security.trustservice.store.TrustCacheJwksChangeListener
kid cache misses.
An active refresher (DefaultJwksRefresher) maintains a small overlay cache of
JsonWebKeySets populated by asynchronous calls to the regional JWKS Fetch Service
(via JwksFetchServiceClient). When a verification path encounters an unknown
kid it calls maybeExpediteRefresh(String, String, String, int) which
(subject to cooldown and in-flight dedup) submits a fetch task to a small bounded thread
pool. Callers then read getOverlay(String) to consult the overlay during key
resolution.
The refresher subscribes to TrustCacheJwksChangeListener:
on onJwksChanged it evicts the overlay entry and repopulates it from the live
endpoint once the authoritative TrustCache rotates keys; on onJwksRemoved
it only evicts, since the issuer is gone and must not be re-fetched. Either way stale
reads are avoided.
Obtain an instance via create(JwksFetchServiceClient, Metrics, Map): when expedited refresh is disabled a no-op
implementation is returned, so callers never have to branch on the feature flag.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intDefault per-JWKS keyset size cap, matchingIDENTITY_PROVIDER_JWKS_DEFAULT_LIMITincc-rbac-services(cc-trust-service/.../IdentityProviderManagerImpl.java). -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()static JwksRefreshercreate(JwksFetchServiceClient fetchClient, org.apache.kafka.common.metrics.Metrics metrics, Map<String, ?> configs) Creates a refresher from broker config.org.jose4j.jwk.JsonWebKeySetgetOverlay(String cacheKey) Returns the overlay-cachedJsonWebKeySetforcacheKey, ornullif absent or expired.voidmaybeExpediteRefresh(String kid, String jwksEndpoint, String cacheKey, int maxJwksKeys) Possibly trigger an asynchronous expedited fetch ofjwksEndpoint.voidregisterChangeListener(io.confluent.security.trustservice.store.TrustCache cache) Registers this refresher ascache'sTrustCacheJwksChangeListener, at most once over the refresher's lifetime.Methods inherited from interface io.confluent.security.trustservice.store.TrustCacheJwksChangeListener
onJwksChanged, onJwksRemoved
-
Field Details
-
DEFAULT_MAX_JWKS_KEYS
static final int DEFAULT_MAX_JWKS_KEYSDefault per-JWKS keyset size cap, matchingIDENTITY_PROVIDER_JWKS_DEFAULT_LIMITincc-rbac-services(cc-trust-service/.../IdentityProviderManagerImpl.java). Used as a floor when computing the per-call cap; the rbac-extractor may accept more keys for individual providers via theTRUST_SERVICE_SCHEDULER_JWKS_LIMIT_FFLaunchDarkly override, in which case the caller should passmax(cachedSet.size(), DEFAULT_MAX_JWKS_KEYS)so the overlay never trims below what TrustCache already holds.- See Also:
-
-
Method Details
-
maybeExpediteRefresh
Possibly trigger an asynchronous expedited fetch ofjwksEndpoint. The call is non-blocking. Subsequent calls for the samecacheKeyare dropped while a fetch is in-flight, and further calls are suppressed during the cooldown window after a completed fetch.- Parameters:
kid- the JWT key id that triggered the miss (used to detect KID_MISSING)jwksEndpoint- upstream JWKS URI to forward to the fetch servicecacheKey- the V2 trust-cache key (issuer:jwksEndpoint)maxJwksKeys- maximum number of keys retained from the fetched keyset; entries beyond this index are dropped to match the upstream TrustCache cap
-
getOverlay
Returns the overlay-cachedJsonWebKeySetforcacheKey, ornullif absent or expired. -
registerChangeListener
void registerChangeListener(io.confluent.security.trustservice.store.TrustCache cache) Registers this refresher ascache'sTrustCacheJwksChangeListener, at most once over the refresher's lifetime.The verification path constructs a new
KafkaVerificationKeyResolverper authentication and resolves the shared singletonTrustCachelazily, so registering directly from that path would re-set the listener on every request — andAbstractAuthCache#setJwksChangeListenerlogs a warning on each overwrite, spamming the logs under load. Implementations must therefore be idempotent and safe under concurrent first-time calls (the active implementation guards with a single compare-and-set).A single broker process owns one
TrustCacheand one refresher singleton, so registering once is sufficient; the refresher does not track multiple caches. -
close
void close()- Specified by:
closein interfaceAutoCloseable- Specified by:
closein interfaceCloseable
-
create
static JwksRefresher create(JwksFetchServiceClient fetchClient, org.apache.kafka.common.metrics.Metrics metrics, Map<String, ?> configs) Creates a refresher from broker config. When expedited refresh is disabled (ConfluentConfigs.OAUTH_JWKS_EXPEDITED_REFRESH_ENABLE) aNoOpJwksRefresheris returned and no resources (thread pool, caches, metrics) are allocated, so the active implementation never has to reason about the disabled case. The tunables (cooldowns, overlay TTL and max entries) are read here soDefaultJwksRefresherstays decoupled from the config system; their defaults live inConfluentConfigs.- Parameters:
configs- the broker config map (already validated against the brokerConfigDef)
-