{"id":15043900,"url":"https://github.com/node-casbin/nest-authz","last_synced_at":"2025-04-08T08:18:19.940Z","repository":{"id":42041442,"uuid":"172611990","full_name":"node-casbin/nest-authz","owner":"node-casbin","description":"Nest.js RBAC \u0026 ABAC authorization module based on Node-Casbin, see example at: https://github.com/node-casbin/nest-authz-example","archived":false,"fork":false,"pushed_at":"2025-03-17T06:01:58.000Z","size":554,"stargazers_count":169,"open_issues_count":0,"forks_count":26,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-01T07:50:43.334Z","etag":null,"topics":["abac","access-control","acl","auth","authorization","authz","casbin","nest-casbin","nestjs","node-casbin","nodejs","rbac"],"latest_commit_sha":null,"homepage":"https://github.com/casbin/node-casbin","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/node-casbin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-26T01:08:24.000Z","updated_at":"2025-04-01T06:31:49.000Z","dependencies_parsed_at":"2024-09-25T01:51:29.982Z","dependency_job_id":"1496db7f-20e6-46fe-bf3e-aacdb1a81b1b","html_url":"https://github.com/node-casbin/nest-authz","commit_stats":{"total_commits":150,"total_committers":15,"mean_commits":10.0,"dds":0.52,"last_synced_commit":"a68f73944736a969020cece08a274c0010e38205"},"previous_names":["dreamdevil00/nest-authz"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-casbin%2Fnest-authz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-casbin%2Fnest-authz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-casbin%2Fnest-authz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-casbin%2Fnest-authz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/node-casbin","download_url":"https://codeload.github.com/node-casbin/nest-authz/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247801176,"owners_count":20998339,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["abac","access-control","acl","auth","authorization","authz","casbin","nest-casbin","nestjs","node-casbin","nodejs","rbac"],"created_at":"2024-09-24T20:49:48.020Z","updated_at":"2025-04-08T08:18:19.918Z","avatar_url":"https://github.com/node-casbin.png","language":"TypeScript","readme":"# nest-authz\n\n[![NPM version][npm-image]][npm-url]\n[![NPM download][download-image]][download-url]\n[![ci](https://github.com/node-casbin/nest-authz/actions/workflows/ci.yml/badge.svg)](https://github.com/node-casbin/nest-authz/actions/workflows/ci.yml)\n[![Coverage Status](https://coveralls.io/repos/github/node-casbin/nest-authz/badge.svg?branch=master)](https://coveralls.io/github/node-casbin/nest-authz?branch=master)\n[![Discord](https://img.shields.io/discord/1022748306096537660?logo=discord\u0026label=discord\u0026color=5865F2)](https://discord.gg/S5UjpzGZjN)\n\n[npm-image]: https://img.shields.io/npm/v/nest-authz.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/nest-authz\n[download-image]: https://img.shields.io/npm/dm/nest-authz.svg?style=flat-square\n[download-url]: https://npmjs.org/package/nest-authz\n\nA access control library for [NestJS](https://nestjs.com/) which built on [node-casbin](https://github.com/casbin/node-casbin).\n\nCasbin is a powerful and efficient open-source access control library. It provides support for enforcing authorization based on various access control models like ACL, RBAC, ABAC. For detailed info, check out the [official docs](https://casbin.org/)\n\n## How to use\n\n### Installation\n\n```bat\n$ npm install --save nest-authz\n```\n\n### Define Access Control Model\n\nFirstly, you should create your own casbin access control model. Checkout [related docs](https://github.com/casbin/node-casbin#supported-models) if you have not.\n\n### Initialization\n\nRegister nest-authz with options in the AppModule as follows:\n\n```\nAuthZModule.register(options)\n```\n\n`options` is an object literal containing options.\n\n- `model` is a path string to the casbin model.\n- `policy` is a path string to the casbin policy file or adapter\n- `enablePossession` is a boolean that enables the use of possession (`AuthPossession.(ANY|OWN|OWN_ANY)`) for actions.\n- `userFromContext` (REQUIRED) is a function that accepts `ExecutionContext`(the param of guard method `canActivate`) as the only parameter and returns the user as either string, object, or null. The `AuthZGuard` uses the returned user to determine their permission internally.\n- `resourceFromContext` (OPTIONAL) is a function that accepts `ExecutionContext` and `PermissionData` and returns an `AuthResource`. This allows the `AuthZGuard` to perform access control on specific resources found in a request. When provided, this function is used as the default for all `Permissions` with `resourceFromContext: true`.\n- `enforcerProvider` Optional enforcer provider\n- `imports` Optional list of imported modules that export the providers which   are required in this module.\n\nThere are two ways to configure enforcer, either `enforcerProvider`(optional with `imports`) or `model` with `policy`\n\nAn example configuration which reads user and resource id from the http request.\n\n```typescript\nimport { TypeOrmModule } from '@nestjs/typeorm';\n\n@Module({\n  imports: [\n    AuthZModule.register({\n      model: 'model.conf',\n      policy: TypeORMAdapter.newAdapter({\n        type: 'mysql',\n        host: 'localhost',\n        port: 3306,\n        username: 'root',\n        password: 'password',\n        database: 'nestdb'\n      }),\n      userFromContext: (ctx) =\u003e {\n        const request = ctx.switchToHttp().getRequest();\n        return request.user \u0026\u0026 request.user.username;\n      },\n      resourceFromContext: (ctx, perm) =\u003e {\n        const request = ctx.switchToHttp().getRequest();\n        return { type: perm.resource, id: request.id };\n      }\n    }),\n  ],\n  controllers: [AppController],\n  providers: [AppService]\n})\n```\n\nor\n\n```typescript\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { ConfigModule, ConfigService } from './config.module';\nimport { AUTHZ_ENFORCER } from 'nest-authz';\n\n@Module({\n  imports: [\n    ConfigModule,\n    AuthZModule.register({\n      imports: [ConfigModule],\n      enforcerProvider: {\n        provide: AUTHZ_ENFORCER,\n        useFactory: async (configSrv: ConfigService) =\u003e {\n          const config = await configSrv.getAuthConfig();\n          return casbin.newEnforcer(config.model, config.policy);\n        },\n        inject: [ConfigService],\n      },\n      userFromContext: (ctx) =\u003e {\n        const request = ctx.switchToHttp().getRequest();\n        return request.user \u0026\u0026 {\n          username: request.user.username, \n          isAdmin: request.user.isAdmin \n        };\n      }\n    }),\n  ],\n  controllers: [AppController],\n  providers: [AppService]\n```\n\nThe latter method of configuring the enforcer is preferred.\n\n### Checking Permissions\n\n#### Using `@UsePermissions` Decorator\n\nThe `@UsePermissions` decorator is the easiest and most common way of checking permissions. Consider the method shown below:\n\n```typescript\n  @Get('users')\n  @UseGuards(AuthZGuard)\n  @UsePermissions({\n    action: AuthActionVerb.READ,\n    resource: 'USER',\n    possession: AuthPossession.ANY\n  })\n  async findAllUsers() {}\n\n```\n\nThe `findAllUsers` method can not be called by a user who is not granted the permission to read any user.\n\nThe value of property `resource` is a magic string just for demonstrating. In the real-world applications you should avoid magic strings. Resources should be kept in the separated file like `resources.ts`\n\nThe param of `UsePermissions` are some objects with required properties `action`, and `resource`, and optionally `possession`, and `isOwn`.\n\n- `action` is an enum value of `AuthActionVerb`.\n- `resource` is a resource string or object the request is accessing.\n- `possession` is an enum value of `AuthPossession`. Defaults to `AuthPossession.ANY` if not defined.\n- `isOwn` is a function that accepts `ExecutionContext`(the param of guard method `canActivate`) as the only parameter and returns boolean. The `AuthZGuard` uses it to determine whether the user is the owner of the resource. A default `isOwn` function which returns `false` will be used if not defined.\n- `resourceFromContext` is either a boolean (which defaults to false) or a function that accepts `ExecutionContext` and `PermissionData` as parameters and returns an `AuthResource`. When set to true, the default `resourceFromContext` function provided during module initialization is used. When set to a function, the provided function will override the default `resourceFromContext` function. When set to false, undefined, or if a default `resourceFromContext` is not provided, the `resource` option will be used as-is for each request.\n\nIn order to support ABAC models which authorize based on arbitrary attributes in lieu of simple strings, you can also provide an object for the resource. For example:\n\n```typescript\n@UsePermissions({\n  action: AuthActionVerb.READ,\n  resource: {type: 'User', operation: 'single'},\n  possession: AuthPossession.ANY\n})\nasync userById(id: string) {}\n\n@UsePermissions({\n  action: AuthActionVerb.READ,\n  resource: {type: 'User', operation: 'batch'},\n  possession: AuthPossession.ANY\n})\nasync findAllUsers() {}\n```\n\nTo provide access control on specific resources, `resourceFromContext` can be used:  \n\n```typescript\n@UsePermissions({\n  action: AuthActionVerb.READ,\n  resource: 'User',\n  resourceFromContext: (ctx, perm) =\u003e {\n    const req = ctx.switchToHttp().getRequest();\n    return { type: perm.resource, id: req.id };\n  }\n})\nasync userById(id: string) {}\n```\n\nYou can define multiple permissions, but only when all of them satisfied, could you access the route. For example:\n\n```\n@UsePermissions({\n  action: AuthActionVerb.READ,\n  resource: 'USER_ADDRESS',\n  possession: AuthPossession.ANY\n}, {\n  action; AuthActionVerb.READ,\n  resource: 'USER_ROLES',\n  possession: AuthPossession.ANY\n})\n```\n\nOnly when the user is granted both permissions of reading any user address and reading any roles, could he/she access the route.\n\n#### Using `AuthZService`\n\nWhile the `@UsePermissions` decorator is good enough for most cases, there are situations where we may want to check for a permission in a method's body. We can inject and use `AuthZService` which is a wrapper of the Casbin RBAC + Management API for that as shown in the example below:\n\n```typescript\nimport { Controller, Get, UnauthorizedException, Req } from '@nestjs/common';\nimport {\n  AuthZGuard,\n  AuthZService,\n  AuthActionVerb,\n  AuthPossession,\n  UsePermissions\n} from 'nest-authz';\n\n@Controller()\nexport class AppController {\n  constructor(private readonly authzSrv: AuthZService) {}\n\n  @Get('users')\n  async findAllUsers(@Req() request: Request) {\n    let username = request.user['username'];\n    // If there is a policy  `p, root, user, read:any` in policy.csv\n    // then user `root` can do this operation\n\n    // Using string literals for simplicity.\n    const isPermitted = await this.authzSrv.hasPermissionForUser(username, \"user\", \"read:any\");\n    if (!isPermitted) {\n      throw new UnauthorizedException(\n        'You are not authorized to read users list'\n      );\n    }\n    // A user can not reach this point if he/she is not granted for permission read users\n    // ...\n  }\n}\n```\n\n\n#### (Deprecated) Using `AuthZRBACService` or `AuthZManagementService`\n\n\u003e The functionality provided by `AuthZRBACService` and `AuthZManagementService` has been unified in `AuthZService`, so these services will be removed in a later release.\n\nWe can inject and use `AuthZRBACService` or `AuthZManagementService` which are wrappers of the Casbin RBAC and Management APIs, respectively, as shown in the example below:\n\n```typescript\nimport { Controller, Get, UnauthorizedException, Req } from '@nestjs/common';\nimport {\n  AuthZGuard,\n  AuthZRBACService,\n  AuthActionVerb,\n  AuthPossession,\n  UsePermissions\n} from 'nest-authz';\n\n@Controller()\nexport class AppController {\n  constructor(private readonly rbacSrv: AuthZRBACService) {}\n\n  @Get('users')\n  async findAllUsers(@Req() request: Request) {\n    let username = request.user['username'];\n    // If there is a policy  `p, root, user, read:any` in policy.csv\n    // then user `root` can do this operation\n\n    // Using string literals for simplicity.\n    const isPermitted = await this.rbacSrv.hasPermissionForUser(username, \"user\", \"read:any\");\n    if (!isPermitted) {\n      throw new UnauthorizedException(\n        'You are not authorized to read users list'\n      );\n    }\n    // A user can not reach this point if he/she is not granted for permission read users\n    // ...\n  }\n}\n```\n\n## Example\n\nFor more detailed information, checkout the working example in\n[nest-authz-example](https://github.com/node-casbin/nest-authz-example)\n\n## License\n\nThis project is licensed under the MIT license.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnode-casbin%2Fnest-authz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnode-casbin%2Fnest-authz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnode-casbin%2Fnest-authz/lists"}