Read on my site.
In this article, i will show you how to create Role based authorization middleware with Casbin and Nest.js. Casbin is an authorization library that supports access control models like ACL, RBAC, ABAC for Golang, Java, PHP and Node.js, but in this article, we will use the Node.js.
Nest is a progressive Node.js framework for building efficient, reliable and scalable server-side applications. It uses Typescript language and support multiple core server like Express, Koa or Fastify.
If you prefer to watch in video format:
Here is the text format:
Before we create the project, install Nest first.
npm i -g @nestjs/cli
And then we create a project with the Nest cli
nest new theproject
Then, open the project directory and install the Casbin
cd theproject
npm install --save casbin
After this, we enter the coding phase.
First, create the policy configuration for Casbin.
In the src, create a directory named casbin_conf.
cd src
mkdir casbin_conf
Create model.conf and policy.csv in the casbin_conf
File model.conf:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
File policy.csv:
p, admin, /*, GET
p, notadmin, /, POST
In the policy we define two rules, one is for user who have admin role and the other is for user who have notadmin role.
After that, we create the Nest middleware.
Create a middleware named authorization.middleware.ts in src
File authorization.middleware.ts:
import { Enforcer } from 'casbin';
export class BasicAuthorizer {
private req: any;
private enforcer: any;
constructor(req, enforcer) {
this.req = req;
this.enforcer = enforcer;
}
getUserRole() {
const { user } = this.req;
const { role } = user;
return role;
}
checkPermission() {
const { req, enforcer } = this;
const { originalUrl: path, method } = req;
const userRole = this.getUserRole();
return enforcer.enforce(userRole, path, method);
}
}
// the authorizer middleware
export function authz(newEnforcer: () => Promise<Enforcer>) {
return async (req, res, next) => {
const enforcer = await newEnforcer();
// user sample
req.user = {role: 'admin'};
if(!(enforcer instanceof Enforcer)) {
res.status(500).json({500: 'Invalid enforcer'});
return;
}
const authorizer = new BasicAuthorizer(req, enforcer);
if(!authorizer.checkPermission()) {
res.status(403).json({403: 'Forbidden'});
return;
}
next();
}
};
That's the authorization middleware logic, Casbin will help checking the permission.
Then we integrate the middleware in Nest project bootstrap.
Find the maint.ts, integrate the authorization middleware in the app:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { newEnforcer } from 'casbin';
import { authz } from './authorization.middleware';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// authorization middleware that is registered as global middleware
app.use(authz(async() => {
const enforcer = await newEnforcer(join(__dirname, 'casbin_conf/model.conf'), join(__dirname, 'casbin_conf/policy.csv'));
return enforcer;
}));
await app.listen(3000);
}
bootstrap();
That is the authorization middleware that is registered as global middleware in the app.
Boot up the project to test:
npm run start:dev
If you want to experiment, modify the sample user in the authz, remove that if you want make it into production.
Here is the project repository.
Top comments (0)