Script Valley
REST API Development: Beginner to Production
Authentication and AuthorizationLesson 4.2

Implementing login and JWT auth middleware in Express

password hashing with bcrypt, login endpoint, issuing JWTs, Authorization header, Bearer token, auth middleware, protecting routes

Building JWT Login and Auth Middleware

Authentication has two parts: issuing a token at login, and verifying it on every protected request.

Login Endpoint

npm install bcrypt jsonwebtoken
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');

app.post('/auth/login', async (req, res, next) => {
  try {
    const { email, password } = req.body;
    const user = await User.findByEmail(email);
    if (!user) return res.status(401).json({ error: 'Invalid credentials' });

    const match = await bcrypt.compare(password, user.passwordHash);
    if (!match) return res.status(401).json({ error: 'Invalid credentials' });

    const token = jwt.sign(
      { sub: user.id, role: user.role },
      process.env.JWT_SECRET,
      { expiresIn: '15m' }
    );
    res.json({ token });
  } catch (err) { next(err); }
});

Auth Middleware

// middleware/auth.js
const authenticate = (req, res, next) => {
  const header = req.headers.authorization;
  if (!header || !header.startsWith('Bearer '))
    return res.status(401).json({ error: 'No token provided' });

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

module.exports = { authenticate };
// Protecting a route
router.get('/profile', authenticate, (req, res) => {
  res.json({ userId: req.user.sub });
});

Up next

Refresh tokens — implementing secure token rotation

Sign in to track progress