zahid ras zahid ras - 3 months ago 22
Node.js Question

What is the best way to implement roles and permission in Express REST Api

I need kind of expert opinion to implement Roles and Permission in Express js. I'm planning to develop Restful Api using Express js but didn't get sufficient information to implement Roles and Permission although there are tons of option are available for authentication and authorization.

Answer

Create Tables

First you need to create your tables that will hold the associations between roles, permissions, and resources:

  1. Create a roles table ('Admin', 'User', 'Guest')
  2. Create a resources table ('Users', 'Projects', 'Programs')
  3. Create a permissions table ('Create', 'Read','Write','Delete','Deny')
  4. Create a junction table with all three tables as sources

You may not need that kind of granularity for the permissions table, but some people like it. For example, you don't really need 'Deny', since you just check for Read != true.

Now when you want the permissions of a role on a resource, you just look up role_id and resource_id and check for which permissions are set to true.

Create Middleware

Since you're using express, middleware will be easy to add. For example, let's say you have a router called users:

users.post('/', getAuth, handleUserPost)

Assuming you have a token of some sort on the request that identifies the user making the post, and attaching the user instance to the request object you can do this:

getAuth = function (req, res, next) {
  if(req.user) { 
    db.getPerms({role_id: req.user.role_id, resource_id: req.resource.id})
       .then(function(perms){
          var allow = false;
          //you can do this mapping of methods to permissions before the db call and just get the specific permission you want. 
          perms.forEach(function(perm){
              if (req.method == "POST" && perms.create) allow = true;
              else if (req.method == "GET" && perms.read) allow = true;
              else if (req.method == "PUT" && perms.write) allow = true;
              else if (req.method == "DELETE" && perm.delete) allow = true;

          })
          if (allow) next();
          else res.status(403).send({error: 'access denied'});
       })//handle your reject and catch here
   } else res.status(400).send({error: 'invalid token'})
}

That code was roughed in just for this example, so I wouldn't go copy and pasting it, but it should give you the right idea.

Comments