An authorization library that supports access control models like ACL, RBAC, ABAC in Node.js and Browser

Overview

Node-Casbin

NPM version NPM download install size codebeat badge GitHub Actions Coverage Status Release Gitter

News: still worry about how to write the correct node-casbin policy? Casbin online editor is coming to help!

casbin Logo

node-casbin is a powerful and efficient open-source access control library for Node.JS projects. It provides support for enforcing authorization based on various access control models.

All the languages supported by Casbin:

golang java nodejs php
Casbin jCasbin node-Casbin PHP-Casbin
production-ready production-ready production-ready production-ready
python dotnet c++ rust
PyCasbin Casbin.NET Casbin-CPP Casbin-RS
production-ready production-ready beta-test production-ready

Documentation

https://casbin.org/docs/en/overview

Installation

# NPM
npm install casbin --save

# Yarn
yarn add casbin

Get started

New a node-casbin enforcer with a model file and a policy file, see Model section for details:

// For Node.js:
const { newEnforcer } = require('casbin');
// For browser:
// import { newEnforcer } from 'casbin';

const enforcer = await newEnforcer('basic_model.conf', 'basic_policy.csv');

Note: you can also initialize an enforcer with policy in DB instead of file, see Persistence section for details.

Add an enforcement hook into your code right before the access happens:

const sub = 'alice'; // the user that wants to access a resource.
const obj = 'data1'; // the resource that is going to be accessed.
const act = 'read'; // the operation that the user performs on the resource.

// Async:
const res = await enforcer.enforce(sub, obj, act);
// Sync:
// const res = enforcer.enforceSync(sub, obj, act);

if (res) {
  // permit alice to read data1
} else {
  // deny the request, show an error
}

Besides the static policy file, node-casbin also provides API for permission management at run-time. For example, You can get all the roles assigned to a user as below:

const roles = await enforcer.getRolesForUser('alice');

See Policy management APIs for more usage.

Policy management

Casbin provides two sets of APIs to manage permissions:

  • Management API: the primitive API that provides full support for Casbin policy management.
  • RBAC API: a more friendly API for RBAC. This API is a subset of Management API. The RBAC users could use this API to simplify the code.

Official Model

https://casbin.org/docs/en/supported-models

Policy persistence

https://casbin.org/docs/en/adapters

Policy consistence between multiple nodes

https://casbin.org/docs/en/watchers

Role manager

https://casbin.org/docs/en/role-managers

Contributors

This project exists thanks to all the people who contribute.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

This project is licensed under the Apache 2.0 license.

Contact

If you have any issues or feature requests, please contact us. PR is welcomed.

Comments
  • Database transactions similar api `addPolicies`, `removePolicies`

    Database transactions similar api `addPolicies`, `removePolicies`

    Hello, recently I'm having another issue, while creating a new user/role, I would like to assign some default rights for it.

    We can definitly call multiple times addPolicy but it cannot guarantee that all the default policies have been added, I'm risking having an invalid user in that case.

    So I'm thinking if we could have some wrappers like addPolicies, removePolicies.

    addPolicies returns Promise<true> only if all the policies have been added, if one of them fails then it cancels this operation (remove the ones have been added)

    removePolicies is similar.

    enhancement help wanted 
    opened by GopherJ 34
  • Extract file handling out (as a plugin?) to enable casbin to be used on React Native

    Extract file handling out (as a plugin?) to enable casbin to be used on React Native

    Hey,

    firstly thanks for this awesome library!

    I noticed that the frontend casbin library uses this under-the-hood, so I'm using this library on both microservice and Frontend.

    However, I'd love to be able to use this library on React Native - which would work, but because the model loading from file uses the fs library, I can't.

    How likely/possible would it be to extract out model loading from a file/file handling to be a plugin/adapter to remove the need for fs? (I load the model and policy dynamically from the microservice).

    Thanks!

    enhancement 
    opened by harveyappleton 29
  • Am using casbin-sequelize-adapter to load the policy from database

    Am using casbin-sequelize-adapter to load the policy from database

    By default, the adapter is creating id, ptype, v0, v1, v2, v3, v4 columns if not exist Can I add more columns to handle the application policies Like application_id as v5, group_id as v6,... etc

    I tried to add the columns but during the retrieval, it's returning only the columns which is created by the adapter.

    question 
    opened by kowthalganesh 27
  • Performance issues with ~20k policies

    Performance issues with ~20k policies

    Was wondering if anyone else is experiencing a slow down even with a relatively low number of policies.

    For our ~20k policies we notice it takes around 5 seconds to evaluate them.

    Here is our conf.

    [request_definition]
    r = type, resourceId, userId, action
    
    [policy_definition]
    p = type, resourceId, userId, action
    
    [policy_effect]
    e = some(where (p.eft == allow))
    
    [matchers]
    m = r.type == p.type && r.resourceId == p.resourceId && r.userId == p.userId && r.action == p.action
    

    We have seemed to narrowed it down to this line in coreEnforcer.ts

    Switching from compileAsync to compile and removing the await brought us down to around 40ms with the same amount of policies.

    enhancement 
    opened by MPiccinato 27
  • Class extends value undefined is not a constructor or null

    Class extends value undefined is not a constructor or null

    When importing casbin in a typescript project for Angular I get this error: image

    For the Model class I've solved by importing like this:

    import { Model } from "casbin/lib/esm/model";
    

    But for newEnforcer there is no way to work around that issue. Am I missing something?

    bug 
    opened by giovanni-bertoncelli 26
  • Module parse failed: Unexpected token (158:32) with create-react-app

    Module parse failed: Unexpected token (158:32) with create-react-app

    getting this error working in react typescript application. Please fix it

    Module parse failed: Unexpected token (158:32) File was processed with these loaders:

    • ./node_modules/babel-loader/lib/index.js You may need an additional loader to handle the result of these loaders. | async buildIncrementalRoleLinks(rm, op, sec, ptype, rules) { | if (sec === 'g') {
      await this.model.get(sec)?.get(ptype)?.buildIncrementalRoleLinks(rm, op, rules);
    

    | } | } // buildRoleLinks initializes the roles in RBAC.

    question 
    opened by ravikumarjs-foyernet 20
  • RoleManager interface return type

    RoleManager interface return type

    I see that the return type of function signature in interface RoleManager are not async value. In fact, all functions related to IO operation in JavaScript should be async, for example:

    getRoles(name: string, ...domain: string[]): string[]; Perhaps it will query database So it should be

    getRoles(name: string, ...domain: string[]): Promise<string[]>

    for compatibility, maybe it can be getRoles(name: string, ...domain: string[]): Promise<string[]> | string[]

    thoughts?

    @nodece @hsluoyz

    enhancement 
    opened by dreamdevil00 20
  • casbinJsGetPermissionForUser is not returning user permission

    casbinJsGetPermissionForUser is not returning user permission

    Hi, I'm using casbin 5.6.1 and wanted to use the function casbinJsGetPermissionForUser to retrieve the list of permissions associated to a user on request, but it returns only a string representation of the model.

    The code doesn't seem to use the user passed in argument.

    I also tried to use await enforcer.getImplicitPermissionsForUser(user); but it returns empty

    this is my model

    [request_definition]
    r = user, domain, path, method
    
    [policy_definition]
    p = role, domain, path, method
    
    [role_definition]
    # map user, role and domain
    g = _, _, _
    # mapping id to global resource
    g2 = _, _
    
    [policy_effect]
    e = some(where (p.eft == allow))
    
    [matchers]
    # map user request to correct role, and validte path and method requested are allowed
    m = g(r.user, p.role, r.domain) && g2(r.domain, p.domain) && keyMatch2(r.path, p.path) && regexMatch(r.method, p.method)
    

    and the policy

    # only correct role can do correct call to these
    p, role:owner, workflow_api, /workflow/:id, (get)|(put)
    p, role:admin, workflow_api, /workflow/:id, get
    
    # gloabl role hierarchy
    g, role:super_admin, role:owner, *
    
    # map user roles to WF ids
    g, User1, role:owner, wf1
    g, User2, role:admin, wf1
    g, User3, role:owner, wf2
    
    # reference the new id to be a valid workflow
    g2, wf1, workflow_api
    g2, wf2, workflow_api
    

    Enforcer itself works fine.

    How can i get the implicit list of roles of my users ?

    bug 
    opened by Anthony-Michel 18
  • Can not add role for a user in case g = _, _, _

    Can not add role for a user in case g = _, _, _

    I have the following role definition:

    [role_definition]
    g = _, _, _
    

    But, when I am trying to add a role for a user, the function addRoleForUser accepts only two parameters (it is hardcoded), so I can not provide the domain.

    Here is the test-case I wrote to check that:

        it('Should properly add new role to user and remove it from the enforcer', async () => {
            const enforcer = await getEnforcer();
    
            assert.deepEqual(await enforcer.getGroupingPolicy(), []);
            // here I am trying to add role, but signature for the method accepts only user and role
            assert.isTrue(await enforcer.addRoleForUser('subject', 'role', 'domain'));
        });
    
    

    So, as a result, I am getting the following error:

    Error: grouping policy elements do not meet role definition
          at Assertion.buildRoleLinks (node_modules/casbin/lib/model/assertion.js:40:23)
          at astMap.forEach.value (node_modules/casbin/lib/model/model.js:123:19)
          at Map.forEach (<anonymous>)
          at Model.buildRoleLinks (node_modules/casbin/lib/model/model.js:122:16)
          at Enforcer.buildRoleLinks (node_modules/casbin/lib/coreEnforcer.js:246:20)
          at Enforcer.<anonymous> (node_modules/casbin/lib/managementEnforcer.js:339:22)
          at Generator.next (<anonymous>)
          at fulfilled (node_modules/casbin/lib/managementEnforcer.js:17:58)
    
    bug enhancement 
    opened by ghaiklor 18
  • [RBAC w/ Domain] Checking for an object/action permission in any domain.

    [RBAC w/ Domain] Checking for an object/action permission in any domain.

    I'm attempting to figure out how to discover if a user has the ability to perform a specific action on an object in any of my domains. Here's basically what I'm working with:

    config

    [request_definition]
    r = sub, dom, obj, act
    
    [policy_definition]
    p = sub, dom, obj, act
    
    [role_definition]
    g = _, _, _
    
    [policy_effect]
    e = some(where (p.eft == allow))
    
    [matchers]
    m = g(r.sub, p.sub, r.dom) && r.obj == p.obj && r.act == p.act
    

    policies

    p, admin, tenant1, data1, read
    p, admin, tenant1, data1, write
    p, admin, tenant1, data2, read
    p, admin, tenant1, data2, write
    p, user, tenant1, data1, read
    p, user, tenant1, data2, read
    
    p, admin, tenant2, data1, read
    p, admin, tenant2, data1, write
    p, admin, tenant2, data2, read
    p, admin, tenant2, data2, write
    p, user, tenant2, data1, read
    p, user, tenant2, data2, read
    
    g, alice, admin, tenant1
    g, bob, user, tenant2
    

    I want to check if Alice has the write action on data1 for any domain. What is the best way to do this?

    I can do an enforce and supply a domain to check if the user has data1 write access, but I can't do it for all domains at once.

    I have attempted to add a custom domain matching function using the following code, but the wildCardDomainMatch doesn't seem to ever be called.

    initialization

        this._permissionEnforcer = await newEnforcer(this._model, this._adapter);
        const rm = new DefaultRoleManager(10);
        await rm.addDomainMatchingFunc(this.wildCardDomainMatch);
        await this._permissionEnforcer.setRoleManager(rm);
        await this._permissionEnforcer.loadPolicy();
    
    

    Domain Match Function

    private wildCardDomainMatch = (requestDomain: string, policyDomain: string): boolean => {
      if (requestDomain === "*") {
          return true;
      }
    
      return requestDomain === policyDomain;
    };
    
    enhancement 
    opened by ShawnPavel 17
  • using both grouping and keyMatch2 in a matcher

    using both grouping and keyMatch2 in a matcher

    im new to casbin and recently using it with nodejs and came across this probably frequent need to use both grouping and keyMatching on a policy , wraping a keyMatch func with g identifier or viseversa doesnt seem to be valid syntax for serving those policies containing resource with pattern

    Screenshot from 2020-04-25 11-02-29

    help wanted question released 
    opened by ghaedi1993 17
  • Add grouping policy for casbinJsGetPermissionForUser

    Add grouping policy for casbinJsGetPermissionForUser

    Previously the casbinJsGetPermissionForUser function would not include the grouping policy in the generated result, I have now added this missing part.

    opened by Gk0Wk 5
  • does the node-casbin support `subjectPriority`?

    does the node-casbin support `subjectPriority`?

    This is the doc: https://casbin.io/docs/priority-model#load-policy-with-priority-based-on-role-and-user-hierarchy Then I place the demo code to the online editor: https://casbin.org/casbin-editor/#53YFYAD7M When I click RUN THE TEST button, it throw unsupported effect!

    enhancement 
    opened by vaseala 3
  • add flag for errors from adapter in internal api

    add flag for errors from adapter in internal api

    @nodece has suggested to add a flag for getting a not-implemented error from the adapter.

    I have a suggestion, add a flag for receiving all errors, meas if true we will throw errors even if it's a not-implemented error.

    need a discussion on this.

    Originally posted by @nodece in https://github.com/casbin/node-casbin/pull/384#discussion_r967673880

    bug 
    opened by Shivansh-yadav13 1
  • using with react (vite)

    using with react (vite)

    I have problem when using node-casbin with react

    import { newModel, Enforcer, newEnforcer } from 'casbin'
    import { AuthActionVerb, AuthPossession, CustomAuthActionVerb } from 'constants/enum/auth'
    import { ExecutionContext } from 'graphql/execution/execute'
    
    import storage from './storage'
    
    export type Permission = {
      resource: string
      action: AuthActionVerb | CustomAuthActionVerb
      possession?: AuthPossession
    }
    
    export const loadModel = () => {
      // rbac model
      const model = `
    	[request_definition]
    	r = sub, obj, act
    
    	[policy_definition]
    	p = sub, obj, act
    
    	[role_definition]
    	g = _, _
    
    	[policy_effect]
    	e = some(where (p.eft == allow))
    
    	[matchers]
    	m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
    
      const m = newModel()
      m.loadModelFromText(model)
      return m
    }
    
    export const loadPermissions = async (enforcer: Enforcer) => {
      const permissions = storage.getPermissions()
      await Promise.all([
        ...permissions.map((permission: any) => {
          return enforcer.addPolicy(permission[0], permission[1], permission[2])
        }),
      ])
    }
    
    export const initEnforcer = async (): Promise<Enforcer | null> => {
      const m = loadModel()
    
      const enforcer = await newEnforcer(m)
    
      await loadPermissions(enforcer)
    
      return enforcer
    }
    

    Screen Shot 2022-09-13 at 4 18 16 PM

    question 
    opened by meodemsao 16
  • [Question] Performance issue with wildcard rbac, is there a better way to do this?

    [Question] Performance issue with wildcard rbac, is there a better way to do this?

    Want to prioritize this issue? Try:

    issuehunt-to-marktext


    What's your scenario? What do you want to achieve?

    I want to find a better way to implement this setup, as performance is really really bad as is.

    Your model:

    [request_definition]
    r = sub, obj, act
    
    [policy_definition]
    p = sub, obj, act
    
    [role_definition]
    g = _, _
    
    [policy_effect]
    e = some(where (p.eft == allow))
    
    [matchers]
    m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && r.act == p.act
    

    Your policy:

    p | ["program-manager-438", "/program/438", "delete"]
    p | ["program-manager-438", "/program/438", "read_mappings"]
    p | ["program-manager-438", "/audit/438/:auditId", "create"]
    p | ["program-manager-438", "/audit/438/:auditId", "delete_attachment"]
    p | ["program-manager-438", "/audit/438/:auditId", "Treatment.Completed"]
    p | ["program-manager-438", "/audit/438/:auditId", "Archived.Completed"]
    p | ["program-manager-438", "/vendor/438/:vendorId", "upload_attachment"]
    p | ["program-manager-438", "/requirement/438/:frameworkOrAuditId/:requirementId", "download_attachment"]
    p | ["program-manager-438", "/requirement/438/:frameworkOrAuditId/:requirementId", "Draft.In-scope"]
    p | ["program-manager-438", "/assessment/438/:auditId/:assessmentId", "delete_mappings"]
    p | ["program-manager-438", "/evidence-request/438/:auditId/:assessmentId/:evidenceRequestId", "read"]
    p | ["program-manager-438", "/evidence-request/438/:auditId/:assessmentId/:evidenceRequestId", "read_mappings"]
    p | ["program-manager-438", "/evidence-request/438/:auditId/:assessmentId/:evidenceRequestId", "Archived.Draft"]
    p | ["program-manager-438", "/finding/438/:auditId/:assessmentId/:findingId", "delete"]
    
    g | john, program-manager-438
    

    Your request(s):

    john, finding/438/33/44/3, read ---> true
    

    Essentially the goal is to have roles that have wildcard rules like this. But also roles that are more specific that use exact ids instead. This works with the implementation above, but has atrocious performance.

    Currently, if you have around 40000 rules, this takes ~500ms to check 10 permissions, and ~1000ms to check 20 permissions...that makes me think that the enforcer is checking them synchronously?

    FYI: My setup is nodejs with postgres adapter.

    question 
    opened by jjh-reciprocity 4
Releases(v5.20.1)
Owner
Casbin
Casbin authorization library and the official middlewares
Casbin
This package allows you to use Okta as your identity provider for use with Netlify's Role-based access control with JWT.

netlify-okta-auth This package allows you to use Okta as your identity provider for use with Netlify's Role-based access control with JWT. Who is this

Twilio Labs 8 Sep 17, 2022
The authentication-server is a node app that handles user registration, authentication & authorization with JWT.

Authentication Server The authentication-server is a node app that handles user registration, authentication & authorization with JWT. Here is the REP

Oğuz Çolak 18 Jul 24, 2022
Oso is a batteries-included library for building authorization in your application.

Oso What is Oso? Oso is a batteries-included library for building authorization in your application. Oso gives you a mental model and an authorization

Oso 2.8k Jan 1, 2023
Tutorial Project : NodeJs API Multi Authorization Middleware with JWT

Tutorial How to Create API with multi route prefixs as well as Multi Authorization in NodeJs Installation npm install .env modify database informatio

Aung Kyaw Nyunt 10 Dec 10, 2022
Boilerplate next.js app demonstrating how to implement authorization mechanisms using Permify

Permify Next.js Authorization Demo App This demo app shows how to implement authorization mechanisms to your Next.js application using Permify Node SD

Permify 7 Apr 22, 2022
EveryAuth is the easiest way for your app to access APIs like Slack, Salesforce, or Github.

EveryAuth EveryAuth is the easiest way for your app to access APIs like Slack, Salesforce, or Github. import everyauth from "@fusebit/everyauth-expres

Fusebit 13 Dec 12, 2022
node.js auth package (password, facebook, & more) for Connect and Express apps

everyauth Authentication and authorization (password, facebook, & more) for your node.js Connect and Express apps. There is a NodeTuts screencast of e

Brian Noguchi 3.5k Dec 17, 2022
Node-sodium-jwt - Fast sodium-based crypto for signing and verifying json web tokens (JWT)

node-sodium-jwt Features Fast sodium-based crypto for hashing json web tokens (JWT) Relies on sodium-native to perform crypto. Built with TypeScript f

Olivier Louvignes 1 Jan 3, 2022
Simple, unobtrusive authentication for Node.js.

Passport Passport is Express-compatible authentication middleware for Node.js. Passport's sole purpose is to authenticate requests, which it does thro

Jared Hanson 21k Jan 7, 2023
node.js/express module to authenticate users without password

Passwordless Passwordless is a modern node.js module for Express that allows authentication and authorization without passwords by simply sending one-

Florian Heinemann 2k Dec 14, 2022
This project shows how you can easily jwt protect your endpoints in web api apps built with node js.

JWT Protected NodeJs API This project shows how you can easily jwt protect your endpoints in web api apps built with node js. It is an easy and simple

Cihat Girgin 3 Oct 19, 2021
Role based authentication for NodeJS and ExpressJS

Authentication service made for ExpressJS and MongoDB using JWT. We tried to make it as clean and structured as possible. We also provide this documentation on how to install and integrate it with your own application.

null 4 Oct 3, 2021
Building an API on nodejs with registration system, authentication, CRUD of projects and tasks.

api-token-express Building an API on nodejs with registration system, authentication, CRUD of projects and tasks. API endpoints POST { "username":

MrDiniz 4 Jan 15, 2022
Authenticated server-side rendering with Nuxt 3 and Firebase 9

Authenticated server-side rendering with Nuxt 3 and Firebase 9.

Robert Soriano 51 Dec 23, 2022
An authorization library that supports access control models like ACL, RBAC, ABAC in modern JavaScript platforms

Casbin-Core ?? Looking for an open-source identity and access management solution like Okta, Auth0, Keycloak ? Learn more about: Casdoor News: still w

Casbin 6 Oct 20, 2022
An OAuth2 Authorization Server,Based on Spring Authorization Server

?? id-server 一个基于Spring Authorization Server的开源的授权服务器。 概念 一些概念 OAuth2Client 客户端指的是OAuth2 Client,但又不单单是一个OAuth2 Client,连id server本身都是一个客户端。 role 角色必须依附

felord.cn 351 Dec 30, 2022
☁️ Application using Node.js, AdonisJs, Adonis ACL, Adonis Kue Provider, Adonis Mail, Adonis Lucid Slugify, Adonis Validator, AdonisJs Redis, ESLint and pg

Node.js - SaaS ☁️ Application using Node.js, AdonisJs, Adonis ACL, Adonis Kue Provider, Adonis Mail, Adonis Lucid Slugify, Adonis Validator, AdonisJs

null 4 Aug 19, 2022
CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access

CASL (pronounced /ˈkæsəl/, like castle) is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to ac

Sergii Stotskyi 4.5k Dec 31, 2022