What Is a JSON Web Token?
A JSON Web Token (JWT) is an open standard (RFC 7519) for securely transmitting information between parties as a compact, URL-safe string. It's the most widely used method for stateless authentication in modern web applications and APIs.
Unlike traditional sessions that require server-side storage, JWTs are self-contained — all the information needed to verify a user's identity is encoded directly in the token.
JWT Structure: Three Parts
A JWT looks like: xxxxx.yyyyy.zzzzz — three Base64URL-encoded sections separated by dots.
1. Header
{ "alg": "HS256", // Signing algorithm "typ": "JWT" // Token type
}2. Payload (Claims)
{ "sub": "user_123", // Subject (user ID) "name": "Jane Developer", // Custom claim "role": "admin", // Custom claim "iat": 1709251200, // Issued at "exp": 1709252100 // Expires at (15 min later)
}Standard claims include iss (issuer), sub (subject), aud (audience), exp (expiration), iat (issued at), and jti (unique ID).
3. Signature
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key
)The signature ensures the token hasn't been tampered with. Only the server holding the secret key can create valid signatures.
The JWT Authentication Flow
- User sends credentials (email/password) to the login endpoint
- Server validates credentials and creates a JWT with the user's claims
- Server returns the JWT to the client
- Client stores the JWT (typically in memory or httpOnly cookie)
- Client sends JWT in the
Authorization: Bearer <token>header on every request - Server verifies the signature and reads claims from the payload
JWT vs Session-Based Auth
| Feature | JWT | Sessions |
|---|---|---|
| Storage | Client-side | Server-side |
| Scalability | Stateless, easy to scale | Requires shared session store |
| Revocation | Harder (need blocklist) | Easy (delete from store) |
| Cross-domain | Works naturally | Needs CORS config |
| Mobile-friendly | Yes | Cookie issues |
Access Tokens and Refresh Tokens
Best practice is to use two tokens:
- Access token — Short-lived (5-15 minutes), sent with every API request
- Refresh token — Long-lived (days/weeks), stored securely, used only to get new access tokens
This minimizes the damage window if an access token is compromised while avoiding frequent re-authentication.
Security Best Practices
- Never store JWTs in localStorage — vulnerable to XSS attacks. Use httpOnly cookies or in-memory storage.
- Keep payloads small — Don't store sensitive data; the payload is only encoded, not encrypted.
- Always validate on the server — Never trust client-side JWT decoding for authorization.
- Use strong secrets — At least 256 bits for HMAC; prefer RS256 (RSA) for distributed systems.
- Set expiration — Always include
expclaim. Short-lived tokens reduce risk. - Implement token rotation — Issue new refresh tokens on each use and invalidate old ones.
Decode and Inspect JWTs
Need to inspect a JWT's claims? Use our JWT Decoder to paste any token and see the decoded header, payload, and signature verification status instantly. For more on token security, read our JWT Token Security Guide.