Using cookie-based JWT Authentication instead of localStorage is becoming a more secure and preferred
practice for Single Page Applications (SPAs) in 2025. This shift addresses key security concerns like XSS and
improves session management. Here’s a clear breakdown of how to implement it.
Why Move from localStorage
to Cookie-Based JWT Authentication?
Feature | localStorage | HTTP-only Cookies |
---|---|---|
XSS Protection | ❌ Vulnerable to JavaScript access | ✅ Cannot be accessed via JavaScript |
Token Handling | ❌ Manual management in frontend | ✅ Sent automatically with requests |
CSRF Protection | ✅ Not needed | ⚠️ Required (mitigation possible) |
Using cookies (with HttpOnly
, Secure
, and SameSite
flags) improves security and reduces boilerplate in your client-side code.
How to Implement Cookie-Based JWT Authentication (Step-by-Step)
1. User Logs In from React Frontend
A login form sends credentials to the backend.
2. Backend Issues JWT and Sets Secure Cookie
Node.js / Express Example:
const jwt = require(‘jsonwebtoken’);
const cookie = require(‘cookie’);
app.post(‘/login’, (req, res) => {
const { username, password } = req.body;
// TODO: Validate credentials
const token = jwt.sign({ userId: 123 }, 'your-secret-key', { expiresIn: '1h' });
res.cookie('token', token, {
httpOnly: true,
secure: true, // only over HTTPS
sameSite: 'Strict', // or 'Lax'
maxAge: 3600000, // 1 hour
});
res.json({ success: true });
});
3. Frontend Sends Requests Automatically with Cookie
React Example using Fetch:
fetch(‘/api/protected’, {
method: ‘GET’,
credentials: ‘include’,
});
Axios Example:
axios.get(‘/api/protected’, { withCredentials: true });
✅ No need to manually store or attach the token.
Middleware to Protect Routes on the Backend
Express Authentication Middleware:
const jwt = require(‘jsonwebtoken’);
function authenticate(req, res, next) {
const token = req.cookies.token;
if (!token) return res.sendStatus(401);
try {
const decoded = jwt.verify(token, ‘your-secret-key’);
req.user = decoded;
next();
} catch {
res.sendStatus(401);
}
}
Apply it to any route that requires authentication.
Logout: Clear the Cookie
res.clearCookie(‘token’, {
httpOnly: true,
sameSite: ‘Strict’,
});
res.json({ success: true });
✅ Important Notes for Cookie-Based JWT
- Always set
HttpOnly
,Secure
, andSameSite
attributes for cookies. - If using
SameSite=None
, CSRF tokens are mandatory. - For
SameSite=Lax
orStrict
, CSRF tokens are optional but still recommended. - Ensure your app is served over HTTPS when using the
Secure
flag.