What Is a JWT?
A JSON Web Token is how most modern APIs prove "this request came from someone who already logged in" without the server having to remember anything. Here's what's actually inside one, and the two mistakes that account for most JWT-related security bugs.
// the shape of a jwt
{"alg":"HS256","typ":"JWT"}// claims worth knowing
ississuer — who created and signed this tokensubsubject — who the token is about, usually a user IDaudaudience — who this token is intended forexpexpiration — a Unix timestamp; the token is invalid after thisnbfnot-before — the token isn't valid until this timestampiatissued-at — when the token was createdEverything past these is application-specific — roles, permissions, tenant IDs, whatever the issuer decided to include. There's no schema enforcement; the payload is just JSON, so anything the signer puts there arrives at the consumer as-is.
// symmetric vs asymmetric signing
HS256 uses one shared secret to both sign and verify — simple, but every service that needs to verify a token also needs the secret that can forge one. RS256 and ES256 use a private/public key pair: only the issuer holds the private key that signs tokens, while any number of services can hold the public key and verify without ever being able to mint a valid token themselves. For anything beyond a single trusted backend, asymmetric signing is almost always the right default.
// the two mistakes that matter
exp pushed into the future or role: admin added by hand. The signature is the only thing that proves the payload wasn't altered after the real issuer signed it — reading claims without verifying first means trusting user input.// try it yourself
Paste a token into the JWT Decoder to see its header and payload broken out, check exp/nbf against the current time, and verify HS256, RS256, or ES256 signatures — entirely in your browser, the token never leaves your machine.
A JWT is three Base64URL-encoded segments joined by dots:
header.payload.signature. Base64URL is the same idea as regular Base64 (see the Base64 Converter) but swaps+//for-/_so the token is safe to put directly in a URL or an HTTP header without escaping.