JSON Web Token (JWT) Security, Signing Algorithms & Token Architecture Runbook
Production engineering runbook on JSON Web Token (RFC 7519) architecture, cryptographic signing mechanics, token lifecycle management, and enterprise security hardening. Compare symmetric HMAC (HS256) versus asymmetric RSA/ECDSA (RS256/ES256), prevent common token vulnerabilities (alg: none, weak secrets, timing attacks), and master stateless session rotation.
1. JWT Structural Anatomy & RFC 7519 Standards
[Header].[Payload].[Signature].
The Header specifies token metadata, primarily the cryptographic signing algorithm (alg, e.g. HS256, RS256, ES256) and the token media type (typ: "JWT"). The Payload contains identity claims categorized into standard registered claims (sub, iss, aud, exp, nbf, iat, jti), public claims, and custom application metadata (such as enterprise permissions and roles). The Signature is calculated by hashing the concatenated header and payload with a cryptographic secret or private key, enabling recipients to verify data integrity and authenticity without contacting an external authentication server.| Token Component | RFC Specification | Typical JSON Payload | Encoding & Verification | Copy |
|---|---|---|---|---|
| Header | Cryptographic algorithm & token specification | {"alg": "HS256", "typ": "JWT"} | Base64URL without padding; public metadata | |
| Payload (Claims) | Subject identity, timestamps & authorization scopes | {"sub": "usr_99", "exp": 1730419200, "role": "admin"} | Base64URL; readable by client unless encrypted (JWE) | |
| Signature | Cryptographic message authentication code (HMAC or digital sig) | HMACSHA256(base64Url(H) + "." + base64Url(P), secret) | Prevents tampering; verified via secret or public key |
2. Cryptographic Signing: Symmetric HMAC vs. Asymmetric RSA & ECDSA
// Generate RFC 7519 compliant HS256 JWT using modern native Web Crypto
async function signJwtHS256(header, payload, secret) {
const enc = new TextEncoder();
const toBase64Url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const h64 = toBase64Url(enc.encode(JSON.stringify(header)));
const p64 = toBase64Url(enc.encode(JSON.stringify(payload)));
const data = enc.encode(`${h64}.${p64}`);
// Import raw secret as HMAC cryptographic key
const key = await crypto.subtle.importKey(
'raw',
enc.encode(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const signature = await crypto.subtle.sign('HMAC', key, data);
const s64 = toBase64Url(signature);
return `${h64}.${p64}.${s64}`;
}3. Common JWT Attack Vectors & Production Hardening
{"alg": "none"} or swapped expected asymmetric public keys into HMAC verification routines. To prevent algorithm switching, authentication handlers must strictly whitelist allowed algorithms at runtime: jwt.verify(token, key, { algorithms: ["HS256"] }).
2. Weak HMAC Secrets & Offline Dictionary Cracking: Because tokens are signed offline, attackers who intercept a valid JWT can run dictionary cracking tools (such as Hashcat or John the Ripper) at millions of hashes per second against weak passphrases. HMAC-SHA256 secrets must consist of at least 256 bits (32 bytes) of cryptographically secure random entropy (e.g. crypto.randomBytes(32).toString("hex")).
3. Timing Attack Vulnerabilities: Naive string comparisons (such as calculatedSig === tokenSig) terminate early on the first mismatched byte, leaking microsecond timing information that allows attackers to sequentially reconstruct valid signatures. Production gateways must utilize constant-time comparison routines like crypto.timingSafeEqual().| Security Vulnerability | Attack Mechanism | Severe Consequence | Architectural Mitigation | Copy |
|---|---|---|---|---|
| Algorithm Confusion | Attacker forces RS256 verifier to execute HS256 using public key | Full authentication bypass; forge arbitrary admin tokens | Explicitly pin algorithms array; never trust header alg parameter | |
| Brute-Force Secret Cracking | Offline dictionary attack on low-entropy shared secret | Complete compromise of signing authority | Enforce 256-bit high-entropy secrets generated via CSPRNG | |
| Signature Stripping | Sending header with alg: none and empty signature component | Forged unverified token accepted as valid session | Hard-reject tokens with empty signature or alg: none | |
| Stale Token Replay | Compromised token used indefinitely without revocation | Unauthorized continuous access after account suspension | Short lifespan (15 min) + Refresh token rotation + JTI blocklist |
4. Token Lifespan, Ephemeral Access & Refresh Token Rotation
HttpOnly; Secure; SameSite=Strict browser cookies inaccessible to JavaScript. When the access token expires, the client calls /auth/refresh. The backend verifies the refresh token against a database table, revokes the used refresh token, issues a brand-new refresh token (Refresh Token Rotation), and returns a fresh short-lived access token. If an already-invalidated refresh token is submitted, the system flags token theft and immediately revokes the entire user session hierarchy.# Standard Client-Server Refresh Token Rotation Cycle
1. Initial Login: POST /auth/login (credentials)
โณ Response: Set-Cookie: refresh_token=opaque_token; HttpOnly; Secure; SameSite=Strict
โณ Response Body: { access_token: "jwt_string", expiresIn: 900 }
2. API Request: GET /api/v1/orders
โณ Header: Authorization: Bearer <access_token>
โณ Response: 200 OK (Processed locally by API gateway without DB lookup)
3. Access Token Expires (15 min elapsed):
โณ GET /api/v1/orders โ 401 Unauthorized (jwt expired)
4. Silent Refresh Cycle: POST /auth/refresh
โณ Browser automatically sends HttpOnly refresh_token cookie
โณ Auth Server checks DB: Is refresh_token active?
- If YES: Invalidates old token, generates new refresh_token, issues new access_token
- If NO (Reused): Alerts security system, invalidates all sessions for user_idRelated Free Online Tools
Put these techniques into practice immediately with our privacy-first browser utilities:
Generate and cryptographically sign JSON Web Tokens (HS256) via Web Crypto with custom headers, claims, and automatic expiration stamps.
Decode, inspect, and verify JSON Web Tokens (JWT) in real-time. Analyze claims, timestamps, and signature validity.
Generate Hash-based Message Authentication Codes (HMAC-SHA256, HMAC-SHA512) with a secret key via Web Crypto.