This guide explains how to implement and use JWKS (JSON Web Key Set) persistent storage in the 10Duke Java Core library.
What is JWKS Persistence?
JWKS persistence provides a caching layer for JWT signature verification keys. Instead of fetching keys from remote endpoint every time, keys are stored locally and retrieved through a multi-tier fallback system.
Key Components
JwksPersistentStore Interface
Implement this interface to provide your own storage backend (database, file system, etc.):
- Store and retrieve public keys
- Manage key lifecycle operations
- Support batch operations
DefaultJwtSignatureVerifierKeyProvider
The service that provides public keys for the application to verify JWTs. This class:
- Supplies public keys to the application for JWT signature verification
- Integrates with JWKS persistent storage
- Implements automatic key loading fallback
- Supports key rotation
How It Works
The DefaultJwtSignatureVerifierKeyProvider class uses a 3-tier fallback strategy when a key is requested:
- Memory Cache - Check in-memory cache first
- Persistent Storage - Fall back to your persistent store if available
- Auto-Reload - Fetch from the original JWKS URL if key is still not found
Application Request → Memory → Persistent Store → JWKS Endpoint
↓ ↓ ↓
Return Key Return Key Fetch & Cache Key
Auto-Reload Requirements
- Must call
DefaultJwtSignatureVerifierKeyProvider.setJwksUrl(String url) or DefaultJwtSignatureVerifierKeyProvider.initFromUrl(String url) at least once to store the JWKS URL
- JWKS endpoint must be accessible during auto-reload
- Network connectivity required
Implementation
Step 1: Create a Persistent Store
Implement the JwksPersistentStore interface for your storage backend:
public class MyPersistentStore implements JwksPersistentStore {
}
Step 2: Configure the Key Provider
Set up the key provider with your persistent store:
JwksPersistentStore store = new MyPersistentStore();
DefaultJwtSignatureVerifierKeyProvider keyProvider =
new DefaultJwtSignatureVerifierKeyProvider(store);
String myJwksUrl = "...";
keyProvider.setJwksUrl(myJwksUrl);
Step 3: Use in Your Application
The key provider handles persistence automatically:
PublicKey key = keyProvider.provide("key-id");
int loadedKeys = keyProvider.loadFromPersistentStore();
Configuration Options
Without Persistence (Default)
DefaultJwtSignatureVerifierKeyProvider keyProvider =
new DefaultJwtSignatureVerifierKeyProvider();
With Persistence
JwksPersistentStore store = new MyPersistentStore();
DefaultJwtSignatureVerifierKeyProvider keyProvider =
new DefaultJwtSignatureVerifierKeyProvider(store);
OAuth Client Integration
public class CustomOAuthClient extends WebAppPkceClient {
@Override
protected void updateSigningKeys(JwtServiceProvider jwtSp) {
return reloadPersistentSigningKeys(jwtSp);
super.updateSigningKeys(jwtSp);
}
}
Monitoring and Debugging
Enable debug logging to monitor key operations:
<logger name="tenduke.sdk.core.service.impl.DefaultJwtSignatureVerifierKeyProvider" level="DEBUG"/>
Log Information
- DEBUG: Cache operations, key loading/saving, auto-reload attempts
- WARN: Auto-reload failures, network issues
- ERROR: JWKS endpoint failures, key parsing errors