~/techpuraistart learning
~/tutorials/build-a-rest-api/05-auth-middleware
intermediate·part 5 of 6·1 min read

Auth middleware

Updated Aug 6, 2026Node.js · Express · Auth

Right now, anyone can call every route in your API. This part adds a middleware that checks for a valid JSON Web Token before letting a request through to protected routes.

Installing a JWT library

bash
npm install jsonwebtoken

Writing the middleware

The middleware reads the Authorization header, verifies the token, and attaches the decoded payload to req for downstream routes to use:

js
const jwt = require('jsonwebtoken');

function requireAuth(req, res, next) {
  const header = req.headers.authorization;
  if (!header?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing bearer token' });
  }

  try {
    req.user = jwt.verify(header.slice(7), process.env.JWT_SECRET);
    next();
  } catch {
    res.status(401).json({ error: 'Invalid or expired token' });
  }
}

Protecting a route

Add the middleware as a second argument to any route you want to protect:

js
app.get('/api/users/:id', requireAuth, asyncHandler(async (req, res) => {
  // req.user is now available here
  const { rows } = await pool.query(
    'SELECT id, name, email FROM users WHERE id = $1',
    [req.params.id]
  );
  res.json(rows[0]);
}));
What this doesn't cover

This middleware only verifies a token — it doesn't issue one. A real login route that checks a password and signs a token with jwt.sign() is a natural next step once this series ends, and follows the same pattern.

Try it yourself

Generate a token manually with jwt.sign({ id: 1 }, process.env.JWT_SECRET) in a Node REPL, then call your protected route with and without an Authorization: Bearer <token> header to see both code paths. Last part: deploying this for free.

← previous4. Connecting a databasenext →6. Deploying for free