Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

JWT Configuration

TL;DR — SCHEMABOUND rotates JWT signing keys without downtime via the JwtConfig trait hierarchy. New tokens are signed with the last configured key; old entries remain valid until explicitly removed. Supports HS256, RS256, and ES256 algorithms configured per-issuer through polymorphic config structs.

Configuration Trait Hierarchy

JWT configuration is pluggable via the JwtConfig trait. Each config type handles a specific signing scenario:

Config TypeUse CaseKey Type
SymmetricJwtConfigInternal service-to-service auth, development modeShared secret (HS256)
AsymmetricJwtConfigExternal IdP verification with public/private key pairsRSA/EC key pair (RS256, ES256)
OidcJwksConfigOIDC discovery-based validation against external providersFetches from JWKS endpoint

Example: Symmetric Configuration (Internal Auth)

#![allow(unused)]
fn main() {
use schemabound::auth::{JwtConfig, SymmetricJwtConfig};

// Single key for signing and validation
let config = SymmetricJwtConfig::new("your-secret-key-here".into());

// Multiple keys for zero-downtime rotation (last entry signs, earlier entries validate)
let config = SymmetricJwtConfig::with_rotation(vec![
    "current_key_abc123".into(),
    "previous_key_def456".into(),  // still validates until removed
]);
}

Example: Asymmetric Configuration (External IdP)

#![allow(unused)]
fn main() {
use schemabound::auth::{JwtConfig, AsymmetricJwtConfig};

let config = AsymmetricJwtConfig::new(
    algorithm: Algorithm::RS256,
    private_key_path: "/etc/schemabound/jwt/rsa-private.pem",
);
}

Example: OIDC Discovery (Entra ID, Okta, Keycloak)

#![allow(unused)]
fn main() {
use schemabound::auth::{JwtConfig, OidcJwksConfig};

let config = OidcJwksConfig::new(
    issuer_url: "https://login.microsoftonline.com/<tenant-id>/v2.0",
    cache_ttl: Duration::from_secs(3600),  // refresh public keys every hour
);
}

Rolling Key Rotation (Symmetric Only)

For internal service-to-service auth using shared secrets, SCHEMABOUND supports zero-downtime key rotation via the JwtConfig trait:

  1. Generate a new signing secret using your preferred secure generator (e.g., openssl rand -hex 32)
  2. Add the new key to the front of the rotation list while keeping the old key at the end
  3. Restart SCHEMABOUND — both keys are now active for validation; new tokens sign with the front entry
  4. Wait until all previously-issued tokens have expired (check exp claim)
  5. Remove the old key from the end of the rotation list and restart

Algorithm Selection

AlgorithmUse CaseKey TypeExample Provider
HS256Internal service-to-service auth; fast signing/validationSymmetric shared secretSelf-signed, development mode
RS256External IdP verification with public/private key pairsAsymmetric RSA (2048+ bit)Okta, Keycloak, Azure AD
ES256External IdP verification; smaller signatures than RSAAsymmetric EC P-256Entra ID, Google Identity Platform

Troubleshooting

“Invalid signature” errors after key rotation

If clients report invalid_signature after adding a new key to the rotation list, verify:

  1. The old key is still listed at the end of the rotation vector
  2. No leading/trailing whitespace in individual keys
  3. The restart completed before new tokens were issued (check SCHEMABOUND logs for “JWT secrets loaded” message)

Expired token errors from IdP-issued JWTs

External IdP tokens have fixed expiration windows (typically 1 hour). If SCHEMABOUND receives token_expired responses but the IdP says the token is valid:

  1. Check system clock synchronization — NTP drift causes timestamp validation failures
  2. Verify issuer URL matches the IdP’s actual issuer URL (trailing slashes matter)