Securing Node.js Routes Using HTTP-only Cookies and Middleware
If you're building a React + Node.js app, storing tokens in HTTP-only cookies is a strong defense against XSS. But it’s not enough — you also need to properly restrict backend routes using middleware.
1. Set the Auth Token Securely
On successful login, send the token as a secure, HTTP-only cookie. This prevents JavaScript access on the client.
res.cookie('token', jwt.sign({ id: user.id }, JWT_SECRET, { expiresIn: '1d' }), {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'Lax',
maxAge: 24 * 60 * 60 * 1000
});
res.status(200).json({ message: 'Logged in' });
2. Middleware to Verify Cookie Token
Protect any route using a simple middleware function that checks for the token in the cookie.
// authMiddleware.js
const jwt = require('jsonwebtoken');
function authenticate(req, res, next) {
const token = req.cookies.token;
if (!token) return res.status(401).json({ error: 'Unauthorized' });
try {
req.user = jwt.verify(token, JWT_SECRET);
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
}
module.exports = authenticate;
3. Apply Middleware to Protected Routes
Use your middleware on any route that requires authentication.
const express = require('express');
const authenticate = require('./authMiddleware');
const router = express.Router();
router.get('/profile', authenticate, (req, res) => {
res.json({ userId: req.user.id });
});
4. Make Authenticated Requests from React
When calling protected routes from React, make sure to include credentials.
const res = await fetch('/api/profile', {
method: 'GET',
credentials: 'include'
});
const data = await res.json();
5. Common Pitfalls
- Cookies not sent? Check that you're using
credentials: 'include'and that the cookie domain matches. - Token never verified? Make sure the backend parses cookies using
cookie-parser. - Token expired or missing? Check expiry and browser cookie settings (esp. with secure cookies on localhost).
Final Advice
Never trust the client. Always validate identity on the server using middleware. If you're not using HTTP-only cookies, assume any token stored in localStorage or sessionStorage can be stolen via XSS.
