npm.io
1.0.0 • Published 2d ago

node-rbac-kit

Licence
SEE LICENSE IN LICENSE
Version
1.0.0
Deps
0
Size
107 kB
Vulns
0
Weekly
0

node-rbac-kit

Enterprise-Grade Role-Based Access Control (RBAC) Engine for Node.js.

node-rbac-kit is a fast, framework-agnostic, TypeScript-first authorization library. It supports hierarchical roles, dynamic context rules, wildcards, multi-tenant SaaS applications, validation, graph export, and caching (In-Memory and Redis) with native adapters for Express and NestJS.


Features

  • Core RBAC: Declarative role and permission maps.
  • Hierarchical Inheritance: Graph-based role resolution with cycle detection.
  • Wildcard Matchers: Glob-like namespace permissions (e.g., loan.* matches loan.approve and loan.create).
  • Dynamic Rules (ABAC): Context-aware authorization (e.g., loan officer can approve only if user and loan branches match).
  • Multi-Tenant SaaS: Complete role, rule, and cache isolation between tenants out of the box.
  • Diagnostics & Explanations: Returns detailed denial reasons, required roles, and missing permissions instead of simple booleans.
  • High-Performance Cache: Memory and Redis caching adapters with automatic invalidation.
  • Visual Graph Exporter: Generate permission graphs/trees for auditing or dashboard UI.
  • Diagnostic Validator: Detect duplicate permissions, unused permissions, circular paths, and missing parent roles.
  • Framework Integrations: Custom NestJS Decorators/Guards and Express middleware.

Installation

npm install node-rbac-kit

Quick Start

import { PermissionEngine, MemoryCacheAdapter } from 'node-rbac-kit';

// 1. Initialize Engine
const engine = new PermissionEngine({
  cache: new MemoryCacheAdapter(300), // cache results for 5 mins
  auditLogger: (event) => {
    console.log(`[RBAC AUDIT] ${event.type} - User: ${event.userId} - Action: ${event.action} - Decision: ${event.decision}`);
  }
});

// 2. Define Roles and Inheritance
engine.defineRole({
  name: 'Officer',
  permissions: ['loan.read']
});

engine.defineRole({
  name: 'Manager',
  inherits: ['Officer'], // Inherits loan.read
  permissions: ['loan.update', 'loan.approve']
});

engine.defineRole({
  name: 'Admin',
  inherits: ['Manager'], // Inherits Officer + Manager permissions
  permissions: ['loan.*', 'report.download'] // Wildcards supported
});

// 3. Define Dynamic context rule
engine.defineRule({
  action: 'loan.approve',
  check: (user, context) => {
    // User can approve only if they belong to the loan's branch
    return user.branchId === context.branchId;
  }
});

// 4. Perform Checks
const checkResult = await engine.check({
  user: { id: 'usr-1', roles: ['Officer'], branchId: 'north-branch' },
  action: 'loan.approve',
  context: { branchId: 'north-branch' }
});

console.log(checkResult.allowed); // false (Officer lacks static permission to approve loans)
console.log(checkResult.explanation);
/*
Output:
{
  decision: 'DENY',
  reason: 'User is missing required permission: "loan.approve".',
  missingPermission: 'loan.approve',
  requiredRoles: ['Manager', 'Admin'],
  currentRoles: ['Officer']
}
*/

Advanced Capabilities

Multi-Tenant SaaS Isolation

Scope roles, permissions, and caches dynamically per tenant.

const engine = new PermissionEngine({
  tenantResolver: (context) => context.tenantId
});

// Define same role name with different structures for different tenants
engine.defineRole({ name: 'Admin', permissions: ['loan.create'] }, 'TenantA');
engine.defineRole({ name: 'Admin', permissions: ['loan.read'] }, 'TenantB');
Redis Caching with Failure Resiliency

If Redis goes down, node-rbac-kit continues to resolve authorization requests dynamically without throwing application-breaking exceptions.

import Redis from 'ioredis';
import { PermissionEngine, RedisCacheAdapter } from 'node-rbac-kit';

const redisClient = new Redis('redis://localhost:6379');
const cache = new RedisCacheAdapter(redisClient, {
  defaultTtlSeconds: 600,
  prefix: 'my-app-rbac'
});

const engine = new PermissionEngine({ cache });
Visual Graph Generation

Exposes structural JSON trees representing your hierarchy—perfect for building visual admin panels.

const graph = engine.getPermissionGraph();
console.log(JSON.stringify(graph, null, 2));
Diagnostics Validator

Scans your system for logical configuration errors.

const result = engine.validate(['loan.read', 'loan.write', 'report.download']);
console.log(result.isValid); // true or false
console.log(result.issues);
// Detects: Circular hierarchies, duplicate permissions, unused permissions, missing parents.

Integrations

Express Middleware

Attach permission checks directly to your routes:

import express from 'express';
import { requirePermission } from 'node-rbac-kit';

const app = express();

app.get('/loans/:id', 
  requirePermission(engine, 'loan.read', {
    getUser: (req) => req.session.user, // Customize user extraction
    getContext: (req) => ({ tenantId: req.headers['x-tenant-id'] }) // Custom context
  }),
  (req, res) => {
    res.send('Loan Details');
  }
);
NestJS Decorators & Guard

Secure controller endpoints using declarative metadata:

import { Controller, Get, UseGuards } from '@nestjs/common';
import { RBACGuard, Permission, HasRole } from 'node-rbac-kit';

@Controller('loans')
@UseGuards(RBACGuard)
export class LoanController {

  @Get()
  @Permission('loan.read')
  findAll() {
    return 'Loans list';
  }

  @Get('admin')
  @HasRole('Admin')
  adminPanel() {
    return 'Admin dashboard';
  }
}

Register the engine as a NestJS provider:

import { Module } from '@nestjs/common';
import { PermissionEngine, RBACGuard } from 'node-rbac-kit';

@Module({
  providers: [
    {
      provide: PermissionEngine,
      useValue: new PermissionEngine()
    },
    {
      provide: 'NESTJS_RBAC_OPTIONS',
      useValue: {
        getUser: (req) => req.user,
        getContext: (req) => ({ tenantId: req.headers['x-tenant-id'] })
      }
    },
    RBACGuard
  ],
  exports: [PermissionEngine]
})
export class SecurityModule {}

License

Custom Non-Commercial (See LICENSE file for details)

Keywords