Express-Authz is an authorization middleware for Express, it's based on Node-Casbin: https://github.com/casbin/node-casbin.
npm install casbin@2 casbin-express-authz@1 --save
npm install casbin@3 casbin-express-authz@2 --save
or you can simply use,
npm install express casbin casbin-express-authz --save
By default casbin-authz supports HTTP Basic Authentication of the form Authentication: Basic {Base64Encoded(username:password)}
To use other HTTP Authentication like Bearer/Digest you can use a custom middleware to define the res.locals.username variable and casbin-authz will automatically pick up the value from the variable.
const { newEnforcer } = require('casbin'); const express = require('express'); const { authz } = require('casbin-express-authz'); const app = express(); const enforcer = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); // set userinfo app.use((req, res, next) => { res.locals.username = getUsernameFromToken(); // Your custom function for retrieving username next(); }); // use authz middleware app.use(authz({ newEnforcer: enforcer })); // response app.use((req, res, next) => { res.status(200).json({ status: 'OK' }); }); app.listen(3000);
This package provides BasicAuthorizer, it uses HTTP Basic Authentication as the authentication method. If you want to use another authentication method like OAuth, you needs to implement Authorizer as below:
import { Enforcer, newEnforcer } from 'casbin'; import { authz, Authorizer } from 'casbin-express-authz'; import * as express from 'express'; const app = express(); class MyAuthorizer implements Authorizer { private e: Enforcer; constructor(e: Enforcer) { this.e = e; } checkPermission(): Promise<boolean> { // do something return true; } } const e = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); app.use( authz({ newEnforcer: e, authorizer: new MyAuthorizer(e), }) ); app.listen(3000);
When the authorizer needs the request and response object to check the permission, one can pass the constructor of the customized Authorizer class instead of an instance.
import { Enforcer, newEnforcer } from 'casbin'; import { authz, AuthorizerConstructor } from 'casbin-express-authz'; import { Request, Response } from 'express'; const app = express(); class MyAuthorizer implements Authorizer { private e: Enforcer; private req: Request; private res: Respons; constructor(req:Request, res:Respons, e: Enforcer) { this.e = e; this.req = req this.res = res } checkPermission(): Promise<boolean> { // do something return true; } } const e = await newEnforcer('examples/authz_model.conf', 'examples/authz_policy.csv'); app.use( authz({ newEnforcer: e, authorizer: MyAuthorizer, }) ); app.listen(3000);
The authorization determines a request based on {subject, object, action}, which means what subject can perform what action on what object. In this plugin, the meanings are:
subject: the logged-on user nameobject: the URL path for the web resource like “dataset1/item1”action: HTTP method like GET, POST, PUT, DELETE, or the high-level actions you defined like “read-file”, “write-blog”For how to write authorization policy and other details, please refer to the Casbin's documentation.
This project is licensed under the Apache 2.0 license.