Structure & Signing
Anatomy of a JWT
A JWT has three Base64URL-encoded, dot-separated parts: header.payload.signature. Header and payload are just encoded JSON — readable by anyone, NOT encrypted. Never put secrets or sensitive data directly in the payload.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFsaWNlIiwiZXhwIjoxNzM2NTAwMDAwfQ.4f7a2c9b...
// Decoded header: {"alg": "HS256", "typ": "JWT"}
// Decoded payload: {"sub": "1234", "name": "Alice", "exp": 1736500000}
// Signature: HMACSHA256(base64url(header) + "." + base64url(payload), secret)
// Standard registered claims:
// sub — subject (user ID) exp — expiration time
// iat — issued at iss — issuer
// aud — audience (who it's intended for)Issuing & Verifying (Node.js)
const jwt = require('jsonwebtoken');
// Sign — HS256 uses one shared secret for both signing and verifying
const token = jwt.sign(
{ sub: user.id, role: user.role }, // keep claims minimal — avoids stale
process.env.JWT_SECRET, // profile data baked into old tokens
{ expiresIn: '15m', issuer: 'my-app', audience: 'my-api' }
);
// Verify — always pin the expected algorithm explicitly, don't trust
// the token's own `alg` header — a known attack swaps RS256 for HS256
// using the public key as the HMAC secret, or claims alg: 'none'
const payload = jwt.verify(token, process.env.JWT_SECRET, {
algorithms: ['HS256'], // reject anything else, even if the token claims it
issuer: 'my-app',
audience: 'my-api',
});
// verify() automatically checks exp and throws if the token has expiredHS256 vs RS256
HS256 is symmetric — one shared secret both signs and verifies, so any service that can verify tokens can also forge them. RS256 is asymmetric — a private key signs, a public key verifies, so a third-party service can validate tokens without ever being trusted to issue new ones. RS256 is the better fit for multi-service architectures where verification happens somewhere the signing key shouldn't live.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free