npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

restify-role-based-auth

v1.0.11

Published

Role-based authorization middleware for Restify API applications.

Downloads

11

Readme

restify-role-based-auth

Is a role-based authorization middleware for Restify API applications. This middleware allows you to manage the authorization of all requests to your Restify API through the use of an Unix-style access control list also known as an ACL. In the API's ACL you define the roles that users belong to, the resources (URL paths) those roles have permissions to access, and the HTTP methods that can be used on said resources.

This Authorization Middleware is meant to be used in conjunction with an Authentication Middleware such as Passport.

Installation

You can add restify-role-based-auth as a dependency through NPM


$ npm i restify-role-based-auth --save

in your project require restify-role-based-auth


// Using default configuration
const roleBasedAuth =  require('restify-role-based-auth')();

or GitLab

$ git clone [email protected]:graphicnetdesign/restify-role-based-auth.git

copy the lib folder to your project, rename it to restify-role-based-auth, and then require index.js


const roleBasedAuth =  require('./restify-role-based-auth/lib/index');

Usage

ACL Policy Definition + Requirements

The Access Control List or ACL is an array of Policy objects which make up the access rules by which the API will be bound. The ACL is a single file written in the JSON syntax and must adhere to the following rules:

  • root of the file must be an array
  • array must contain at least one policy object
  • policy objects are JOSN objects each containing the folloing properties:
    • 'role' a String that identifies the user role to which the policy is to be applied
    • 'action' a String that specifying whether the policy is 'allow'ing or 'deny'ing the 'permissions' in the policy
    • 'permissions' an Array of permission objects each containing the following properties:
      • 'resource' a String that identifies the resource route being protected
      • 'methods' an Array of Strings that identifies all of the HTTP verbs that are being protected on the identified resource route

Example

[
  {
    "role": "user",
    "permissions": [{
      "resource": "users",
      "methods": [
        "POST",
        "GET",
        "PUT"
      ],
      "action": "allow",
    }]
  }
]

ACL File + Writing Policies

First step is to create your ACL file, name it acl.json and place this in the config folder in the root of your application. This is the file where you will define all of the role policies that restrict or give access to certain resources within your application.

This middleware will iterate through the ACL in an attempt to match:

  1. the authenticated user's role with a role in one of the ACL's policies
  2. the resource requested (the URI path in the HTTP request) with a resource in one of the permissions objects in the policy
  3. the HTTP method from the request with a method in the methods array within the permission object

If all matches can be found the action in the policy is then checked:

  1. if allow, the middleware will call next() and allow the application to move to the next middleware in the middleware stack
  2. if deny, the middleware will call next() passing it a restify-errors UnauthorizedError with either the default message or the error message supplied in the config object

In the example below, we are:

  • allowing the admin role the rights to all resources (routes) and all methods (HTTP verbs) within the API. This is done through the use of the * (wildcard symbol), we want admins to be able to do anything
  • denying the user role the rights to call the POST method (HTTP verb) on the user resource (route), we do not want logged in users to create more users

Example


[
  {
    "role": "admin",
    "permissions": [{
      "resource": "*",
      "methods": "*",
      "action": "allow"
    }]
  }, 
  {
    "role": "user",
    "permissions": [{
      "resource": "users",
      "methods": [
        "POST"
      ],
      "action": "deny"
    }]
  }
]

Proper Middleware Placement

This middleware depends on each Restify request object having an authenticated user object already attached to it by an authentication middleware like Passport.

The middleware looks for a user object on the restify req object like this req.user. Keep in mind, with the generic use of hasOwnProperty on the user object, you are required to attach a POJO (plain old JavaScript object) to the req object at the point of authentication by your authentication middleware (such as passport). If you attach a complex object, such as a Mongoose model object, this middleware will not be able to find the role(s) property on that user object.

The middleware looks for req.user with a role or roles property that is either a single role as a String or an Array of multiple String roles respectively, from which it can grab the current user's role(s) for verification within the ACL policies list.

This means that the call to server.use(roleBasedAuth()); must come after your call to your authentication middleware or custom code that authenticates the user and adds a user object to the current request.

Example

  // Passport using middleware using passport-jwt strategy
  // attaches a user object to the request if successful
  // authentication occurs
  server.use(passport.initialize());

  // restify-role-based-auth middleware depends on the user 
  // obect and its role property
  server.use(roleBasedAuth);

Customize Middleware

The restify-role-based-auth middleware function can take two parameters:

  • config object with custom values for available configuration properties
Middleware require + invocation signature

require('restify-role-based-auth')([config])

Configuration Object

When requiring the middleware into your application you have the opportunity to use either the default or a custom configuration object.

Default: the middleware will use presets and expects to find your acl.json file in the config folder at the root of your application (./config/acl.json).

  • config object's properties:
    • aclFilename: the name of the ACL Policy file (default: acl.json)
    • aclPath: the file path to the folder containing the ACL Policy file (default: ./config)
    • baseApiUrl: the base URL of the API the middleware is protecting, prepended to all Policy protected resources (default: /)
    • errorMessage: the message to be returned with the 401 Unauthorized Error

Using a custom configuration, in the example below, the middleware will look for your ACL file at the path ./security/custom.json

Example: Custom Config


const customConfig = {
    aclFilename:   'custom.json',
    aclPath:       './security',
    baseApiUrl:    '/api',
    errorMessage:  'You are not authorized to access this resource'
};

const roleBasedAuth =  require('restify-role-based-auth')(customConfig);

Error Response Object: 401 Unauthorized

By default, the middleware will utilize the restify-errors library when determining an error to use and return to the API caller.


## Other Features

### Unless to Bypass
In order to maintain the highest security possible, this middleware takes the lockdown approach, 
that is it blocks all resources (routes) to begin with and only allows resources to be accessed 
if-and-only-if that resources has a defined policy with in the ACL Policy file.

This of course, means that even your authentication resources are locked down, making it so that 
users cannot login or register for the API. To mitigate this effect, the middleware utilizes the 
[express-unless](https://github.com/jfromaniello/express-unless/blob/master/README.md) package 
to allow you to unlock certain resources without the need to setup crazy policies in your ACL. 


```js

const openResources = {
    path: [
      {
        url: '/auth', 
        methods: [
          'POST'
        ]
      },
      {
        url: '/auth/login', 
        methods: [
          'POST'
        ]
      }
    ]
  };

server.use(roleBasedAuth).unless(openResources);

Debug

This middleware supports debug mode through the use of the debug NPM module. Please refer to debug's documentation for turning on and off debugging and adjusting environment variables.

Through the use of debug, the middleware allows you to pull output for all execution paths with the middleware or for specific portions of execution using the following named debug groups.

All namespaced debug statements will be prefixed with 'RRBA:' for easy identification of debug output originating from this middleware.

Debugging can be activated by setting the DEBUG environment variable at application startup.

In development


DEBUG=* node your-apps-index.js

On a server, such as staging or production, you can use a NPM package like dotenv to manage the loading of your environment variables based on the current environment using a .env file placed at the root of your application.

|Debug Key|Description| |:---|:---| |*|All output from the entire middleware as it executes| |RRBA:processors:authorizationProcessor|output from only the Authorization Processor| |RRBA:index|output from only the root of the middleware|