Building a Role-Based Access Control System in Node.js and React

Updated: Jul 14, 2025

AuthenticationSecurityNode.jsReactRBAC
Cover image for "Building a Role-Based Access Control System in Node.js and React"

Building a Role-Based Access Control System in Node.js and React

Role-Based Access Control (RBAC) is essential to secure your app by restricting what users can do based on their roles. Here’s how to implement RBAC using JWT, Express middleware, and React context.

1. Define Roles and Permissions

Start by defining roles and their permissions in your backend:


// roles.js
const roles = {
  admin: ['read:any', 'write:any', 'delete:any'],
  editor: ['read:any', 'write:any'],
  user: ['read:own', 'write:own']
};

module.exports = roles;
  

2. Add Role to JWT Token on Login

Include user role info in the JWT token when logging in:


const token = jwt.sign(
  { id: user.id, role: user.role },
  JWT_SECRET,
  { expiresIn: '1d' }
);
res.cookie('token', token, { httpOnly: true, secure: true, sameSite: 'Lax' });
res.status(200).json({ message: 'Logged in' });
  

3. Create Middleware to Check Permissions

Middleware verifies token and checks if user role has required permission:


// authMiddleware.js
const jwt = require('jsonwebtoken');
const roles = require('./roles');

function authorize(permission) {
  return (req, res, next) => {
    const token = req.cookies.token;
    if (!token) return res.status(401).json({ error: 'Unauthorized' });

    try {
      const user = jwt.verify(token, JWT_SECRET);
      req.user = user;
      const userPermissions = roles[user.role] || [];
      if (!userPermissions.includes(permission)) {
        return res.status(403).json({ error: 'Forbidden' });
      }
      next();
    } catch {
      res.status(401).json({ error: 'Invalid token' });
    }
  };
}

module.exports = authorize;
  

4. Protect Routes with Permission Checks

Use middleware with required permission for each route:


const express = require('express');
const authorize = require('./authMiddleware');

const router = express.Router();

router.get('/admin', authorize('read:any'), (req, res) => {
  res.json({ message: 'Welcome admin!' });
});

router.post('/edit', authorize('write:any'), (req, res) => {
  res.json({ message: 'Edit successful' });
});
  

5. Access Permissions in React

Use React Context or hooks to control UI based on user role and permissions.

Example: Show admin button conditionally:


{user.role === 'admin' && (
  <button onClick={handleAdminAction}>Admin Panel</button>
)}
  

Final Thoughts

RBAC adds powerful control but requires thoughtful design. Keep roles and permissions centralized and verify them server-side for security.