DEV Community

Cover image for express-access: Elegant Role-Based Access Control for Express.js
Bahador Raghibizadeh
Bahador Raghibizadeh

Posted on • Edited on

express-access: Elegant Role-Based Access Control for Express.js

If you're tired of writing repetitive access checks in your Express.js routes, express-access is a lightweight package that brings clean and dynamic role-based access control (RBAC) to your server โ€” without the boilerplate.


๐Ÿš€ Why use express-access?

  • โœ… Clean route definitions with permission checks
  • ๐Ÿ”„ Fully customizable auth and permission logic
  • ๐Ÿงฉ Integrates with any database (SQL, NoSQL, ORM, etc.)
  • ๐Ÿ“ฆ Lightweight with zero dependencies

โœจ Quick Example

import express from 'express';
import access from 'express-access';

const app = express();

app.use(access.config({
  authMiddleware: async (req, res, next) => {
    // Simulate user retrieval (e.g., from JWT or session)
    const uid = 'user1';
    const user = await db.users.findById(uid);
    req.user = { uid: user.id, roleId: user.role_id };
    next();
  },

  checkPermission: async (user, permissionId) => {
    const permissions = await db.role_permissions.findAll({
      where: { role_id: user.roleId },
      attributes: ['permission_id'],
    });
    const allowed = permissions.map(p => p.permission_id);
    return allowed.includes(permissionId);
  },
}));

app.get('/', (req, res) => {
  res.send('Public Route');
});

// Protected route with permission "post:edit"
app.access.get('/edit-post', 'post:edit', [
  (req, res) => {
    res.json({ success: true, message: 'Post editing allowed' });
  }
]);

app.listen(3000, () => console.log('Server running on port 3000'));
Enter fullscreen mode Exit fullscreen mode

๐Ÿง  How It Works

express-access lets you define:

  1. authMiddleware: You attach the authenticated user object (e.g., from JWT/session) to req.user.
  2. checkPermission: You define how a permission string like 'post:edit' is validated against the current user. This function receives the full user object โ€” not just a user ID โ€” so you can access roles, groups, or even account types.

๐Ÿ—‚๏ธ Suggested Database Structure

A common and scalable RBAC setup:

users

Image description

roles
Image description

role_permissions
Image description


๐Ÿงช Real Flow Example

Letโ€™s say user1 makes a request to /edit-post:

  1. authMiddleware attaches:

    req.user = { uid: 'user1', roleId: 'editor' };
    
  2. checkPermission pulls all permission IDs for the role editor:

    ['post:read', 'post:edit']
    
  3. Since 'post:edit' exists, access is granted.

  4. The handler runs. โœ… Clean and secure.


๐Ÿ’ก Tips

  • You can cache permissions per role for performance (e.g., Redis).
  • You can easily support multiple roles per user.
  • Permissions can be strings like post:edit, user:create, etc.
  • Works great with Sequelize, Prisma, or raw queries.

๐Ÿ“ฆ Install

npm install express-access
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฉ Open Source

Feel free to contribute or check out the full source code on GitHub:
๐Ÿ”— https://github.com/bahador-r/express-access


๐Ÿ™Œ Final Thoughts

RBAC shouldnโ€™t be hard to implement. express-access gives you the building blocks to do it elegantly, with full control over your logic and database. Perfect for SaaS products, admin panels, APIs, and anywhere you need clean authorization.

Top comments (0)