For the complete documentation index, see llms.txt. This page is also available as Markdown.

Key Rotation

Rotate JWT signing keys without invalidating in-flight tokens using the kid header.

Rotating signing keys regularly is a security must — limits the blast radius if a key leaks, and gives you a clean break from compromised algorithms. The kid (key ID) JOSE header makes this safe: each token carries the ID of the key that signed it, and verifiers look up the right key dynamically.

bx-jwt makes this pattern straightforward by combining the named key registry with jwtDecode().

The Rotation Pattern

  1. Stamp the kid header when issuing — tells consumers which key signed the token.

  2. Decode without verifying when consuming — read the kid to pick the right key.

  3. Verify with the selected key — never trust the decoded claims until verification succeeds.

// 1. Sign with kid stamped in the header
token = jwtCreate( { sub: "u1" }, "api-signing-v2", "RS256", {
    headers: { kid: "v2" }
} );

// or with the fluent builder
token = jwtNew()
    .subject( "u1" )
    .expireIn( 3600 )
    .header( "kid", "v2" )
    .sign( "api-signing-v2", "RS256" );
// 2 + 3. Verify with the right key per token
function verifyWithKeyRotation( token ) {
    var decoded = jwtDecode( token );           // header only — claims NOT trusted yet
    var kid     = decoded.header.kid ?: "default";
    return jwtVerify( token, kid, decoded.header.alg );   // looks up "kid" in the registry
}

Registry-Driven Rotation

Keep multiple key versions in the registry. Active key signs new tokens; older keys remain available so existing tokens still verify until they expire.

When you cut over:

  1. Add api-signing-v2 to the registry.

  2. Update defaultSigningKey (or the explicit name passed to jwtCreate()).

  3. Stamp the new kid in the header.

  4. Leave api-signing-v1 in place until the longest-lived existing token has expired.

  5. Remove v1 from the registry.

Verifying Tokens From External Issuers

The same pattern handles third-party tokens — register their public keys with the kid they advertise:

Runtime Rotation From a KMS

If your keys come from a key-management service, register them at runtime through JWTService:

Caveats

  • Always decode before verifying. Treat kid as a lookup hint — never authoritatively trust anything in jwtDecode()'s output.

  • Constrain the algorithm. Use allowedAlgorithms so an attacker cannot substitute an unexpected algorithm by changing the token header.

  • Default to a safe fallback. If kid is missing or unknown, reject the token — do not silently fall back to a primary key.

Last updated

Was this helpful?