Express Route Protection With Middlewares
Protecting routes with auth middlewares is the heart of Express security. Here is how.
Express Route Protection With Middlewares
Protecting routes is what makes an Express API secure. Here is how to do it with middlewares.
The Auth Middleware
const auth = (req, res, next) => {
const token = req.cookies.token || req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'Not authenticated' });
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid token' });
}
};
Applying to Single Routes
router.get('/me', auth, getMe);
router.patch('/me', auth, updateMe);
Applying to a Router
router.use(auth); // all routes below require auth
router.get('/posts', listPosts);
router.post('/posts', createPost);
Applying to All Routes in app.js
app.use('/api', auth);
app.use('/api/users', require('./routes/users'));
Public vs Protected Routes
Keep public routes outside any auth router:
// public
router.post('/signup', signup);
router.post('/login', login);
// protected
router.use(auth);
router.get('/me', getMe);
router.patch('/me', updateMe);
router.post('/logout', logout);
Role-Based Auth
A second middleware for roles:
const requireAdmin = (req, res, next) => {
if (req.user.role !== 'admin') return res.status(403).json({ error: 'Not authorized' });
next();
};
router.use('/admin', auth, requireAdmin);
Resource Ownership
For routes like /users/:id, ensure req.user owns the resource:
router.patch('/posts/:id', auth, async (req, res, next) => {
const post = await Post.findById(req.params.id);
if (!post) return next(new ApiError(404, 'Post not found'));
if (post.authorId.toString() !== req.user.id) return res.status(403).json({ error: 'Not authorized' });
// update
});
The Takeaway
Protect Express routes with an auth middleware that verifies the JWT and sets req.user. Apply it to single routes, a router, or in app.js. Keep public routes outside. Use role middlewares for admin. Check ownership for user-specific resources.
Write an auth middleware that verifies the JWT and sets req.user. Apply it to single routes, to a router (router.use(auth)), or in app.js. Keep public routes outside the auth middleware.
Read from req.cookies.token or req.headers.authorization (Bearer token). Verify with jwt.verify(token, process.env.JWT_SECRET). If valid, set req.user and call next; if not, return 401.
Add a second middleware after auth that checks req.user.role. If not allowed, return 403. Apply with router.use('/admin', auth, requireAdmin). Stack middlewares for layered auth.
In the handler, load the resource and compare its owner to req.user.id. If they do not match, return 403. Do this for any user-specific resource like /posts/:id.
Put public routes (signup, login) outside any auth middleware. Then call router.use(auth) and put protected routes below. This keeps the structure clear and prevents accidental auth on public endpoints.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

