JAVASCRIPT

Implement Simple Role-Based Access Control (RBAC) in Express

Set up a basic role-based access control (RBAC) middleware in an Express application to restrict routes and resources based on user roles and permissions.

const express = require('express');
const app = express();
const PORT = 3000;

// Mock User Database (in a real app, this would come from a DB and a secure auth flow)
const users = [
  { id: 1, username: 'admin', roles: ['admin', 'user'] },
  { id: 2, username: 'editor', roles: ['editor', 'user'] },
  { id: 3, username: 'viewer', roles: ['user'] },
];

// Middleware to simulate authentication and attach user to req
// In a real app, this would involve JWT verification, session checks, etc.
function authenticateUser(req, res, next) {
  const authHeader = req.headers['authorization'];
  if (!authHeader) {
    return res.status(401).json({ message: 'Authentication required' });
  }

  // For simplicity, using username as a 'bearer token' for this example
  const token = authHeader.split(' ')[1]; 
  const user = users.find(u => u.username === token);

  if (!user) {
    return res.status(403).json({ message: 'Invalid token or user not found' });
  }

  req.user = user; // Attach user object to request
  next();
}

// RBAC Middleware factory
function authorizeRoles(allowedRoles) {
  return (req, res, next) => {
    if (!req.user || !req.user.roles) {
      return res.status(403).json({ message: 'Access Denied: No user roles found' });
    }

    const hasPermission = req.user.roles.some(role => allowedRoles.includes(role));

    if (hasPermission) {
      next();
    } else {
      res.status(403).json({ message: 'Access Denied: Insufficient permissions' });
    }
  };
}

app.use(express.json());
app.use(authenticateUser); // Apply authentication to all subsequent routes

// Example routes with different access controls
app.get('/api/dashboard', (req, res) => {
  res.json({ message: `Welcome to the dashboard, ${req.user.username}! You are a ${req.user.roles.join(', ')}.` });
});

app.get('/api/admin-panel', authorizeRoles(['admin']), (req, res) => {
  res.json({ message: 'Welcome to the admin-only panel!' });
});

app.post('/api/articles', authorizeRoles(['admin', 'editor']), (req, res) => {
  res.json({ message: `Article created successfully by ${req.user.username}.` });
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});
How it works: This Node.js Express snippet illustrates a simple role-based access control (RBAC) system. It includes an `authenticateUser` middleware that mimics user login (in a real application, this would involve robust authentication like JWTs or sessions) and attaches a `user` object with associated `roles` to the request. The `authorizeRoles` factory function then creates middleware that checks if the authenticated user possesses any of the specified roles. This pattern allows developers to easily restrict access to certain routes or API endpoints based on a user's permissions, ensuring only authorized individuals can perform specific actions and adhering to the principle of least privilege.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs