JWT Authentication: A Complete Deep Dive
Everything you need to know about JWT — how it works, common vulnerabilities, and how to implement it securely.
JSON Web Tokens (JWT) are everywhere. But they’re also widely misimplemented. This guide covers how JWT actually works, the mistakes that create security vulnerabilities, and how to do it right.
What is a JWT?
A JWT is a compact, URL-safe string with three base64url-encoded parts separated by dots:
Decoded:
The signature verifies the token hasn’t been tampered with. The payload is not encrypted — it’s just base64 encoded. Anyone can read it.
Standard Claims
| Claim | Meaning |
|---|---|
sub |
Subject (usually user ID) |
iat |
Issued at (timestamp) |
exp |
Expiration time |
nbf |
Not before |
iss |
Issuer |
aud |
Audience |
jti |
JWT ID (for revocation) |
Secure Implementation in Go
Refresh Token Pattern
Short-lived access tokens + long-lived refresh tokens:
Critical Security Mistakes
1. The alg: none Attack
Never accept tokens with alg: none. Always verify the algorithm:
2. Storing JWT in localStorage
localStorage is vulnerable to XSS. Store access tokens in memory and refresh tokens in httpOnly cookies:
3. Weak Secrets
For HS256, use at least 256 bits of entropy:
For production, prefer RS256 (RSA) or ES256 (ECDSA) — asymmetric algorithms allow public verification without sharing the private key.
4. Not Validating Claims
Always check exp, iss, and aud:
5. Sensitive Data in Payload
Don’t store sensitive data (passwords, PII) in JWT payload. It’s base64 decoded by anyone:
JWT vs Sessions
| JWT (stateless) | Sessions (stateful) | |
|---|---|---|
| Server storage | None | Session store (Redis) |
| Revocation | Hard (need denylist) | Easy (delete session) |
| Horizontal scaling | Easy | Needs shared session store |
| Performance | Token validation | Redis lookup |
| Token size | ~500 bytes | ~32 bytes (session ID) |
Use sessions when: You need instant revocation (e.g., “log out all devices”) Use JWT when: You need stateless, horizontally scalable auth
Neither is universally better — choose based on your requirements.