Roles and requireRole

Authentication and authorization get confused all the time. Authentication answers 'who are you'. Authorization answers 'what are you allowed to do'. The JWT handles the first. A role check handles the second.

after/middlewares/auth.ts
typescript
export function requireRole(role: string) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user) {
      res.status(401).json({ error: 'Unauthorized: User not authenticated' });
      return;
    }

    if (req.user.role !== role) {
      res.status(403).json({ error: 'Forbidden: Requires ' + role + ' role' });
      return;
    }

    next();
  };
}

A middleware factory. You call requireRole("admin") and it returns a middleware tailored to that role.

Notice the shape: requireRole is a function that returns a middleware. That is the factory pattern in Express. You call it once with the role you care about, and it returns a brand new middleware configured for that role. That is how you write parameterized middleware without monkey patching the framework.

after/routes/book.routes.ts
typescript
import { requireAuth, requireRole } from '../middlewares/auth';

bookRouter.get('/', bookController.getBooksHandler);         // public
bookRouter.get('/:id', bookController.getBookHandler);       // public

bookRouter.post(
  '/',
  requireAuth,
  requireRole('admin'),
  bookController.createBookHandler,
);

bookRouter.delete(
  '/:id',
  requireAuth,
  requireRole('admin'),
  bookController.deleteBookHandler,
);

Chain middleware to require both authentication and admin role.

Public routes stay unchanged. GET endpoints are open. POST and DELETE now require a logged-in admin. Express runs the middleware in order: requireAuth first, then requireRole, then the handler. If any middleware sends a response without calling next, the chain stops there.

Quiz: Quiz

Loading practiceโ€ฆ