Auth

JWT

A compact signed token in JSON format that carries claims about a user or permissions.

What it is

A JWT has three dot-separated parts: header, payload and signature, each Base64URL. The signature guarantees the data was not altered, but the payload is not encrypted, so keep no secrets in it.

A server can verify the token without hitting the database: a key is enough. That suits distributed systems and microservices. The downside: revoking an issued token before expiry is hard.

JWT is most often used as an access token in OAuth 2.0 and an ID token in OIDC. Pin the signing algorithm explicitly (for example RS256 or ES256) and reject alg: none.

Use it when

  • Stateless authorization between services and APIs.
  • ID token and access token in OAuth 2.0 / OIDC.
  • Short-lived signed messages (email confirmation links).

Avoid it when

  • Classic web sessions of a single app: a server session with a cookie is simpler and easy to revoke.
  • Storing sensitive data in the payload.

Key concepts

Header / Payload / Signature
Algorithm, claims and signature.
Registered claims
iss, sub, aud, exp, iat.
HS256 vs RS256
A shared secret versus a private and public key pair.
JWKS
A set of public keys for verifying signatures.

Example

Issuing and verifying a JWT with the jose library.

Cheat sheet

JWT cheat sheet
Command or codeWhat it does
header.payload.signatureToken structure: three parts separated by dots
{ "alg": "HS256", "typ": "JWT" }Header: signing algorithm and type
{ "sub": "42", "exp": 1893456000 }Payload: claims about the user and expiry
Authorization: Bearer <token>Send the token in a request header
subWho the token belongs to (user id)
exp / iat / nbfExpiry, issued at and not before (Unix seconds)
iss / audWho issued the token and who it is for
await new SignJWT({ sub }).setProtectedHeader({ alg: "ES256" }).setExpirationTime("15m").sign(key)Issue a token with the jose library
const { payload } = await jwtVerify(token, key, { audience: "api" })Verify signature and claims in jose
Set-Cookie: token=...; HttpOnly; Secure; SameSite=LaxStore the token in a safe cookie

How to learn it

  1. Understand what a JWT is: three parts (header, payload, signature) encoded in base64url but not encrypted.
  2. Decode any token on jwt.io and look at the claims: sub, iat, exp, iss, aud.
  3. Issue and verify a token in code with a library (jose, jsonwebtoken), first with HS256, then RS256 or ES256.
  4. Learn the difference between symmetric and asymmetric signing and when you need JWKS.
  5. Implement an access and refresh token scheme: short access, refresh rotation, revocation.
  6. Decide where to store the token in the browser: httpOnly cookie versus localStorage, and the risks (XSS, CSRF).
  7. Avoid common traps: the none algorithm, algorithm confusion, checking exp, aud, iss, secrets in the frontend.
  8. Learn when you do not need JWT: plain server sessions are often simpler and safer.

Interview questions

  1. 1. Does a JWT encrypt data?

    No, a signed JWT only protects integrity. The payload can be read by Base64URL decoding, so sensitive data does not go there. JWE exists for encryption.

  2. 2. How do you revoke a JWT?

    Keep a short lifetime, rotate refresh tokens and keep a denylist of jti ids for critical cases. Fully stateless revocation is impossible.

  3. 3. Why is alg: none dangerous?

    An attacker can forge an unsigned token if the server trusts the header. So the algorithm is fixed on the server, not taken from the token.

Interview questions from the bank

Logos belong to their owners and are used for identification only. Icons: Simple Icons (CC0), Devicon (MIT).