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

Role-based access control (RBAC) in Express APIs

roles in JWT payload, authorize middleware, role hierarchy, permission checking, admin vs user routes, least privilege principle

Role-Based Access Control

Authentication answers 'who are you?' — authorization answers 'what can you do?' RBAC assigns permissions based on roles attached to users.

Authorize Middleware

// middleware/auth.js
const authorize = (...roles) => (req, res, next) => {
  if (!req.user) return res.status(401).json({ error: 'Not authenticated' });
  if (!roles.includes(req.user.role))
    return res.status(403).json({ error: 'Insufficient permissions' });
  next();
};

module.exports = { authenticate, authorize };
// routes/admin.js
const { authenticate, authorize } = require('../middleware/auth');

// Only admins can access this route
router.delete('/users/:id', authenticate, authorize('admin'), deleteUser);

// Both admins and moderators can access this
router.patch('/posts/:id/status', authenticate, authorize('admin', 'moderator'), updateStatus);

// Any authenticated user
router.get('/profile', authenticate, getProfile);

Resource Ownership Check

// A user can only update their own profile
const canUpdateUser = async (req, res, next) => {
  if (req.user.role === 'admin') return next(); // admins bypass
  if (req.user.sub !== req.params.id)
    return res.status(403).json({ error: 'Cannot modify another user' });
  next();
};

Always apply the least-privilege principle — default to deny, explicitly grant. Include the role in the JWT payload so authorization is stateless. For complex permission systems, consider ABAC (attribute-based access control) or a library like CASL.

Up next

Securing passwords — bcrypt hashing and common mistakes

Sign in to track progress