Script Valley
Express.js: APIs and Middleware
Authentication and AuthorizationLesson 4.2

How to write JWT authentication middleware in Express

jwt.verify, Authorization header, Bearer token extraction, 401 vs 403, req.user from token, token expiry handling, JsonWebTokenError, middleware placement

JWT Authentication Middleware

The auth middleware extracts the token from the Authorization header, verifies it, and attaches the decoded payload to req.user.

authenticate middleware

const jwt = require('jsonwebtoken');
const SECRET = process.env.JWT_SECRET || 'dev_secret';

function authenticate(req, res, next) {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Authorization header required' });
  }

  const token = authHeader.split(' ')[1];

  try {
    const decoded = jwt.verify(token, SECRET);
    req.user = decoded; // { userId, role, iat, exp }
    next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(401).json({ error: 'Token expired' });
    }
    return res.status(401).json({ error: 'Invalid token' });
  }
}

module.exports = authenticate;

Protecting routes

const authenticate = require('./middleware/authenticate');

// Protect a single route
app.get('/profile', authenticate, (req, res) => {
  res.json({ user: req.user });
});

// Protect an entire router
app.use('/api/admin', authenticate, adminRouter);

Use 401 (Unauthorized) when no valid token is present. Use 403 (Forbidden) when a token is valid but the user lacks permissions — keep this distinction consistent.

Up next

Role-based access control (RBAC) middleware in Express

Sign in to track progress