Hash Generator (MD5, SHA-1, SHA-256)
Use Hash Generator (MD5, SHA-1, SHA-256) - Free online tool
Traditional session-based authentication requires the server to maintain a session store. Every request hits the database to validate the session. JWT (JSON Web Token) flips this: the token itself contains everything needed for verification. The server doesn't need to store sessions. Just sign the token with a secret, send it to the client, and verify the signature on each request. This stateless approach scales beautifully and powers modern APIs, mobile apps, and microservices.
This guide covers JWT structure, how they work, when to use them, security best practices, and real-world implementation examples.
JWT (JSON Web Token) is a self-contained token that encodes information about a user or entity in a cryptographically signed format. It's three Base64-encoded parts separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ↓ [HEADER].[PAYLOAD].[SIGNATURE]
The header specifies the token type and signing algorithm:
{ "alg": "HS256", // Algorithm: HMAC SHA-256 "typ": "JWT" // Token type } Base64 encoded: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
The payload contains claims—data about the user:
{ "sub": "user123", // Subject (user ID) "email": "john@example.com", // Custom claim "role": "admin", // Custom claim "iat": 1516239022, // Issued at (timestamp) "exp": 1516325422 // Expiration time } Base64 encoded: eyJzdWIiOiJ1c2VyMTIzIiwiZW1haWwiOiJqb2huQGV4YW1wbGUuY29tIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYzMjU0MjJ9
Standard Claims:
The signature proves the token hasn't been tampered with:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key ) Result: SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c Only the server with secret_key can create valid signatures.
1. User logs in with credentials POST /login { username: "john", password: "secret" } 2. Server verifies credentials, creates JWT token = sign({ sub: "user123", email: "john@..." }, secret) 3. Server sends token to client Response: { token: "eyJhbGc..." } 4. Client stores token (localStorage, sessionStorage, cookie) 5. Client sends token with each request GET /api/profile Authorization: Bearer eyJhbGc... 6. Server verifies signature (no database lookup needed) If signature valid and token not expired → request allowed 7. Stateless verification complete (no session storage needed)
| Feature | JWT | Session |
|---|---|---|
| Storage | Stateless (client-side) | Stateful (server) |
| Scalability | Scales easily (no DB) | Requires shared store |
| Mobile-friendly | ✅ Perfect | ❌ Poor (cookies) |
| Cross-domain | ✅ Works easily | ❌ CORS issues |
| Instant logout | ❌ Hard (token valid until exp) | ✅ Easy (delete session) |
const jwt = require('jsonwebtoken'); const secret = process.env.JWT_SECRET; // 1. Create JWT on login app.post('/login', (req, res) => { const user = { id: 123, email: 'john@example.com' }; const token = jwt.sign(user, secret, { expiresIn: '1h' // Token valid for 1 hour }); res.json({ token }); }); // 2. Verify JWT on protected routes app.get('/api/profile', (req, res) => { const token = req.headers.authorization?.split(' ')[1]; try { const decoded = jwt.verify(token, secret); // Token valid, decoded contains user data res.json({ user: decoded }); } catch (err) { res.status(401).json({ error: 'Invalid token' }); } });
// 1. Login and store token async function login(email, password) { const res = await fetch('/login', { method: 'POST', body: JSON.stringify({ email, password }) }); const { token } = await res.json(); localStorage.setItem('jwt_token', token); } // 2. Send token with requests async function fetchProtectedResource() { const token = localStorage.getItem('jwt_token'); const res = await fetch('/api/profile', { headers: { 'Authorization': `Bearer ${token}` } }); return res.json(); }
For better security, use short-lived access tokens + long-lived refresh tokens:
// Short-lived access token (15 minutes) const accessToken = jwt.sign(user, secret, { expiresIn: '15m' }); // Long-lived refresh token (7 days, stored securely) const refreshToken = jwt.sign(user, refreshSecret, { expiresIn: '7d' }); // When access token expires, use refresh token to get new one POST /refresh Body: { refreshToken } Response: { accessToken } (new 15-min token)
JWT tokens are foundational to modern API authentication. Understanding their structure and security implications is essential for building scalable, secure web applications.