JSON Web Token (JWT)
JSON Web Tokens (JWT) provide a compact, URL-safe means of representing claims securely between two parties. They are commonly used for authentication and authorization in web applications.
What is JWT?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
JWTs can be:
- Signed using a secret (with the HMAC algorithm) or a public/private key pair (RSA or ECDSA)
- Encrypted to also provide secrecy between parties
JWT Structure
A JWT consists of three parts separated by dots (.):
xxxxx.yyyyy.zzzzz
- Header (xxxxx): Contains token type and signing algorithm
- Payload (yyyyy): Contains claims (user data and metadata)
- Signature (zzzzz): Ensures the token hasn’t been altered
JWT Token Structure Visualization
graph LR
A[JWT Token] --> B[Header]
A --> C[Payload]
A --> D[Signature]
B --> B1[Base64Url Encoded]
C --> C1[Base64Url Encoded]
B1 --> E["{
alg: 'HS256',
typ: 'JWT'
}"]
C1 --> F["{
sub: '1234567890',
name: 'John Doe',
iat: 1516239022,
exp: 1516242622
}"]
D --> G["HMACSHA256(
base64UrlEncode(header) + '.' +
base64UrlEncode(payload),
secret)"]How JWT Works
JWT authentication follows a simple flow:
- User logs in with credentials
- Server validates credentials and generates a JWT
- JWT is returned to the client
- Client stores the JWT (typically in local storage or a cookie)
- Client sends the JWT with subsequent requests
- Server validates the JWT signature and processes the request
JWT Authentication Flow
sequenceDiagram
participant User
participant Client
participant Server
User->>Client: Enter credentials
Client->>Server: Authentication request
Note right of Server: Validate credentials
Server->>Server: Generate JWT with payload and signature
Server->>Client: Return JWT
Note left of Client: Store JWT
loop For each protected request
Client->>Server: Request with JWT in Authorization header
Note right of Server: Validate JWT signature
Note right of Server: Check expiration
Server->>Client: Protected resource/response
endJWT Claims
Claims are statements about an entity (typically the user) and additional metadata. There are three types of claims:
Registered Claims: Predefined claims providing a set of useful, interoperable claims
iss(issuer)sub(subject)aud(audience)exp(expiration time)nbf(not before)iat(issued at)jti(JWT ID)
Public Claims: Custom claims defined by those using JWTs
- Should be registered in the IANA JSON Web Token Registry or named using a collision-resistant name
Private Claims: Custom claims created to share information between parties
JWT Implementation Example
Here’s a simplified example of generating and validating a JWT:
Server-side: Generating a JWT (Node.js)
const jwt = require('jsonwebtoken');
// User authentication function
function authenticate(username, password) {
// Validate user credentials (simplified)
if (isValidUser(username, password)) {
// Create token payload
const payload = {
sub: getUserId(username),
name: username,
role: getUserRole(username),
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour expiration
};
// Generate and sign token
const token = jwt.sign(payload, process.env.JWT_SECRET);
return token;
}
throw new Error('Authentication failed');
}
Server-side: Validating a JWT (Node.js)
const jwt = require('jsonwebtoken');
// Middleware to validate JWT
function verifyToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers['authorization'];
if (bearerHeader) {
// Extract token from "Bearer <token>"
const token = bearerHeader.split(' ')[1];
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(403).json({ message: 'Invalid or expired token' });
}
// Add decoded user info to request object
req.user = decoded;
next();
});
} else {
res.status(401).json({ message: 'Access denied. No token provided.' });
}
}
JWT Storage Security Diagram
graph TD
A[JWT Storage Options] --> B[Browser Storage]
A --> C[HTTP Only Cookie]
B --> D[localStorage]
B --> E[sessionStorage]
B --> F[Memory Variable]
D --> G[Pros: Simple, Persists]
D --> H[Cons: XSS Vulnerable]
E --> I[Pros: Session-bound]
E --> J[Cons: XSS Vulnerable]
F --> K[Pros: Not accessible via XSS]
F --> L[Cons: Lost on refresh]
C --> M[Pros: XSS Protected, CSRF can be mitigated]
C --> N[Cons: Server config required]
style C fill:#c9e7f9
style M fill:#c9f9d9Best Practices for JWT
Use HTTPS: Always transmit JWTs over HTTPS to prevent token theft through network eavesdropping
Set Proper Expiration: Use short expiration times and implement token refresh
graph LR A[Token Types] --> B[Access Token] A --> C[Refresh Token] B --> D[Short lived: 15min - 1hr] C --> E[Longer lived: days/weeks] B --> F[Frequent validation] C --> G[Stored securely server-side]Validate All Claims: Check issuer, audience, expiration, and all other relevant claims
Keep Tokens Small: Include only necessary data in the payload to maintain performance
Secure Storage: Store tokens securely, preferably in HttpOnly cookies for web applications
Implement Token Revocation: Have a strategy for invalidating tokens when needed (logout, password change)
Use Strong Keys: Use strong, randomly generated secrets for signing tokens
JWT vs Session Authentication
graph TB
subgraph "JWT Authentication"
A1[Client] -->|1. Login| B1[Server]
B1 -->|2. JWT Token| A1
A1 -->|3. Request with JWT| B1
B1 -->|4. Validate JWT & Respond| A1
end
subgraph "Session Authentication"
A2[Client] -->|1. Login| B2[Server]
B2 -->|2. Session ID Cookie| A2
A2 -->|3. Request with Cookie| B2
B2 -->|4. Lookup Session & Respond| B2
end
C[Comparison]
C --> D[JWT: Stateless, no session storage]
C --> E[Session: Stateful, session storage required]
C --> F[JWT: Larger request size]
C --> G[Session: Smaller request size]
C --> H[JWT: Decentralized validation possible]
C --> I[Session: Centralized validation required]Common JWT Security Vulnerabilities
None Algorithm Attack: Ensure your JWT library rejects tokens with the “none” algorithm
Algorithm Confusion: Ensure proper algorithm verification is implemented
Missing Signature Validation: Always validate signatures, never trust just the presence of a token
Weak Secrets: Use strong, random secrets or keys for token signing
Token Sidejacking: Implement additional security measures to prevent token theft
Further Reading
- JWT.io - Official JWT website with interactive debugger
- RFC 7519 - The JWT specification
- OWASP JWT Cheat Sheet
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.