JWTs are everywhere in modern web apps - authentication headers, API access control, session management. But using them incorrectly is one of the most common security mistakes developers make. This guide covers the essentials: what JWTs are, how they work, and how to use them safely.
What is a JWT?
A JWT (JSON Web Token) is Base64-encoded JSON that is digitally signed to prevent tampering. It is NOT an encrypted vault - anyone who intercepts the token can read its contents. The signature only proves the data was not modified, not that it is secret.
Token Structure
A JWT has three parts separated by dots: header.payload.signature
- Header - Specifies the signing algorithm (e.g., HS256 or RS256)
- Payload - Contains claims: user ID, roles, expiry, and other data
- Signature - Verifies the token was not tampered with
Decode any JWT at jwt.io - remember, the payload is readable by anyone.
How Authentication Works
- User logs in with credentials
- Server validates and returns a signed JWT
- Client stores the token (preferably in memory or httpOnly cookie)
- Every request sends the token in the Authorization header
- Server verifies the signature on each request
No database lookup needed per request - that's the key efficiency win.
Token Revocation Problem
JWTs are stateless by design - once issued, they're valid until expiry. This makes revocation tricky. Common solutions:
- Short expiry times - Keep access tokens to 15 minutes or less
- Refresh tokens - Long-lived tokens stored securely, used to get new access tokens
- Blocklist - Store revoked token IDs in Redis (sacrifices some statelessness)
Security Best Practices
Always verify the signature - Never trust payload data without verifying first.
Set short expiry - Long-lived tokens are a bigger risk if stolen.
Use httpOnly cookies - Prevents JavaScript from reading the token (blocks XSS attacks).
Avoid sensitive data in payload - The payload is only encoded, not encrypted.
Use RS256 over HS256 - Asymmetric keys mean the verification key can be public.
Validate all claims - Check exp, iss, aud every time.
Signing Algorithms
| Algorithm | Type | Use Case |
|---|---|---|
| HS256 | Symmetric (shared secret) | Simple apps, single server |
| RS256 | Asymmetric (public/private key) | Microservices, third-party clients |
| ES256 | Asymmetric (elliptic curve) | Performance-sensitive apps |
HS256 is fine for small projects. RS256 or ES256 are better for production systems.
Quick Recap
- JWTs are signed, not encrypted - never store secrets in payload
- Keep tokens short-lived
- Store in httpOnly cookies when possible
- Always validate signature and claims server-side
- Use refresh token rotation for better security
Top comments (0)