JWT and Session Auth Patterns
Comparison of JWT vs session auth, secure token storage, refresh token patterns, and common pitfalls.
Syntax
environments-and-security
// JWT structure | sign | verify | refresh | storageExample
environments-and-security
// JWT: three parts separated by dots
// header.payload.signature
// eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIn0.abc123
// Sign a JWT
import jwt from 'jsonwebtoken';
const token = jwt.sign(
{ userId: user.id, role: user.role }, // payload
process.env.JWT_SECRET, // secret
{ expiresIn: '15m' } // short-lived access token
);
// Verify a JWT
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
} catch (err) {
return res.status(401).json({ error: 'Invalid token' });
}
// Refresh token pattern
// Access token: short-lived (15min), stored in memory
// Refresh token: long-lived (7 days), stored in httpOnly cookie
// SECURE cookie storage
res.cookie('refresh_token', refreshToken, {
httpOnly: true, // not accessible via JS
secure: true, // HTTPS only
sameSite: 'strict', // CSRF protection
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
// NEVER store tokens in localStorage (XSS vulnerable)
// NEVER put sensitive data in JWT payload (it's base64 decoded, not encrypted)