Key rotation
The backend controls key rotation through the JWKS endpoint.
Key ordering
The client uses the first key in the JWKS response for new request encryption.
{
"keys": [
{ "kid": "current-key", "alg": "RSA-OAEP-256", "use": "enc", "kty": "RSA" },
{ "kid": "previous-key", "alg": "RSA-OAEP-256", "use": "enc", "kty": "RSA" }
]
}
The client must not sort or reorder keys. Backend order is authoritative.
Normal rotation
Recommended backend behavior:
- Publish a new public key as the first JWKS key.
- Keep previous keys available for a transition period.
- Reject requests encrypted with keys that are no longer accepted for new requests by returning
JWE_UNKNOWN_KEY_ID.
Client refresh
The client refreshes JWKS:
- periodically, based on a client-side refresh interval (default 300 seconds),
- on demand when the backend returns
JWE_UNKNOWN_KEY_ID.
Retry behavior
When the backend returns:
{
"status": 400,
"code": "JWE_UNKNOWN_KEY_ID"
}
The client:
- Refreshes JWKS.
- Selects the first key from the refreshed JWKS.
- Creates a new request JWE.
- Creates a new request-local response CEK.
- Creates a new
JWE-Response-Key. - Retries the original request once.
If the retry fails again with JWE_UNKNOWN_KEY_ID, the typed error is returned to the application. No third request is sent.
Why one backend retry code is enough
The client action is identical for these backend situations:
- the
kidis truly unknown, - the
kidis known but no longer accepted, - the client cached an outdated JWKS,
- the client talks to a backend instance with newer key state.
For all these cases, the client should refresh JWKS and retry once. Therefore the backend can use one code:
JWE_UNKNOWN_KEY_ID