JWT Tokens
JWT creation, validation, refresh token rotation, and secure token storage patterns
You are an expert in JSON Web Tokens (JWT) for securing applications. You understand token structure, signing algorithms, refresh strategies, and the trade-offs between stateless and stateful token validation. ## Key Points - **Header**: Specifies the signing algorithm (e.g., RS256, ES256, HS256) and token type. - **Payload (Claims)**: Contains registered claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`) and custom claims. - **Signature**: Produced by signing the encoded header and payload with a secret or private key. - **Access Token**: Short-lived token (5–15 minutes) used to authorize API requests. - **Refresh Token**: Longer-lived token used to obtain new access tokens without re-authentication. - **Token Rotation**: Issuing a new refresh token with every access token refresh, invalidating the old one. - **JWK / JWKS**: JSON Web Key Sets allow public key distribution for signature verification. 1. **Use asymmetric algorithms (RS256, ES256)** for any system where multiple services verify tokens. Reserve HS256 for single-service setups only. 2. **Keep access tokens short-lived** (5–15 minutes). This limits the damage window if a token is leaked. 3. **Always validate `iss`, `aud`, `exp`, and `alg`** on verification. Never skip claim checks. 4. **Store refresh tokens server-side** in a database with revocation capability. Never store them in localStorage. 5. **Implement refresh token rotation** with family-based replay detection to mitigate token theft.
skilldb get auth-patterns-skills/JWT TokensFull skill: 151 linesJWT Tokens — Authentication & Authorization
You are an expert in JSON Web Tokens (JWT) for securing applications. You understand token structure, signing algorithms, refresh strategies, and the trade-offs between stateless and stateful token validation.
Core Philosophy
Overview
JSON Web Tokens provide a compact, self-contained mechanism for transmitting claims between parties. A JWT consists of three Base64URL-encoded segments: header, payload, and signature. JWTs are widely used for API authentication, single sign-on, and information exchange because they can be verified without contacting an authorization server on every request.
Core Concepts
- Header: Specifies the signing algorithm (e.g., RS256, ES256, HS256) and token type.
- Payload (Claims): Contains registered claims (
iss,sub,aud,exp,nbf,iat,jti) and custom claims. - Signature: Produced by signing the encoded header and payload with a secret or private key.
- Access Token: Short-lived token (5–15 minutes) used to authorize API requests.
- Refresh Token: Longer-lived token used to obtain new access tokens without re-authentication.
- Token Rotation: Issuing a new refresh token with every access token refresh, invalidating the old one.
- JWK / JWKS: JSON Web Key Sets allow public key distribution for signature verification.
Implementation Patterns
Signing and Verifying (Node.js with jsonwebtoken)
const jwt = require('jsonwebtoken');
// Signing with RS256 (asymmetric — preferred for distributed systems)
function signAccessToken(userId, roles) {
return jwt.sign(
{ sub: userId, roles, type: 'access' },
process.env.JWT_PRIVATE_KEY,
{
algorithm: 'RS256',
expiresIn: '15m',
issuer: 'auth.example.com',
audience: 'api.example.com',
}
);
}
// Verification middleware
function verifyToken(req, res, next) {
const header = req.headers.authorization;
if (!header?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Missing token' });
}
try {
const decoded = jwt.verify(header.slice(7), process.env.JWT_PUBLIC_KEY, {
algorithms: ['RS256'],
issuer: 'auth.example.com',
audience: 'api.example.com',
});
req.user = decoded;
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid token' });
}
}
Refresh Token Rotation
async function refreshTokens(currentRefreshToken) {
const payload = jwt.verify(currentRefreshToken, process.env.JWT_REFRESH_SECRET);
// Check if this refresh token has already been used (replay detection)
const tokenRecord = await db.refreshTokens.findOne({ jti: payload.jti });
if (!tokenRecord || tokenRecord.revoked) {
// Possible token reuse attack — revoke entire family
await db.refreshTokens.updateMany(
{ family: payload.family },
{ $set: { revoked: true } }
);
throw new Error('Refresh token reuse detected');
}
// Revoke old token
await db.refreshTokens.updateOne({ jti: payload.jti }, { $set: { revoked: true } });
// Issue new pair
const newJti = crypto.randomUUID();
const accessToken = signAccessToken(payload.sub, payload.roles);
const refreshToken = jwt.sign(
{ sub: payload.sub, jti: newJti, family: payload.family },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: '7d' }
);
await db.refreshTokens.insertOne({ jti: newJti, family: payload.family, revoked: false });
return { accessToken, refreshToken };
}
JWKS Endpoint Verification (Python)
import jwt
from jwt import PyJWKClient
JWKS_URL = "https://auth.example.com/.well-known/jwks.json"
jwk_client = PyJWKClient(JWKS_URL, cache_keys=True, lifespan=3600)
def verify_access_token(token: str) -> dict:
signing_key = jwk_client.get_signing_key_from_jwt(token)
return jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience="api.example.com",
issuer="auth.example.com",
)
Best Practices
- Use asymmetric algorithms (RS256, ES256) for any system where multiple services verify tokens. Reserve HS256 for single-service setups only.
- Keep access tokens short-lived (5–15 minutes). This limits the damage window if a token is leaked.
- Always validate
iss,aud,exp, andalgon verification. Never skip claim checks. - Store refresh tokens server-side in a database with revocation capability. Never store them in localStorage.
- Implement refresh token rotation with family-based replay detection to mitigate token theft.
- Use the
jticlaim to give every token a unique ID for revocation and audit. - Transmit tokens only over HTTPS. Set cookies with
Secure,HttpOnly, andSameSite=Strict. - Keep payloads lean. Avoid embedding sensitive data — JWTs are encoded, not encrypted.
Common Pitfalls
- Using
nonealgorithm: Always explicitly specify allowed algorithms during verification to prevent algorithm-switching attacks. - Storing JWTs in localStorage: Vulnerable to XSS. Use HttpOnly cookies or in-memory storage with refresh tokens.
- No token revocation strategy: Pure stateless JWTs cannot be revoked. Maintain a deny-list or use short-lived tokens with refresh rotation.
- Bloated payloads: Large JWTs increase request size on every API call and may exceed header limits.
- Symmetric secrets in distributed systems: Sharing an HS256 secret across services means any compromised service can forge tokens for all others.
- Ignoring clock skew: Use a small
clockTolerance(e.g., 30 seconds) to handle minor time drift between servers.
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add auth-patterns-skills
Related Skills
API Key Auth
API key generation, hashing, rotation, scoping, and rate limiting patterns
Multi Tenancy
Multi-tenant authentication isolation, tenant-scoped tokens, and data boundary enforcement
Oauth2 Flows
OAuth 2.0 authorization code, PKCE, client credentials, and token exchange patterns
Passkeys
Passkeys and WebAuthn implementation for passwordless authentication
Rbac
Role-based access control design, permission hierarchies, and enforcement patterns
Session Management
Server-side session handling, cookie security, session stores, and fixation prevention