MongoDB + Node JS + Role Based Access Control (RBAC)

We are currently studying MEAN stacks by developing a simple TODO application and want to implement role-based access control (RBAC) for this. How to configure roles and permissions on MongoDB.

I want 3 roles (roles may look funny, but this is necessary for learning):

  • GOD
  • SUPER HERO
  • MAN

GOD - looks like a super administrator, can do anything in the application. C, R, U, D for TODO and for other users. Can create TODO and assign it to any SUPER HERO or MAN directly. Update or delete TODO or the user at any given time.

SUPER HERO - like admin, has the super ability to do anything on his personal data - C, R, U, D for TODO. Unable to create users. Can only read and add comments for TODO created by GOD and assigned to him / her.

MAN - can only read and add comments to his assigned TODO.

Summarizing:

GOD - C,R,U,D [Global Level] SUPER HERO - C,R,U,D [Private] + R,U [Assigned to him] MAN - R,U [Assigned to him]

I understand that I need the USERS and ROLES collections. Where roles inturn should have permissions etc. How can I connect them all?

+7
javascript mongodb rbac
source share
3 answers

I like the names for the roles - GOD, SUPER HERO and MAN , which are easy to understand.

Since you are using the MEAN stack, and most of the route checking happens on node , I would rather just keep the role table.

Roles

 { _id : 1, name : GOD, golbalPerms : true }, { _id : 2, name : SUPER HERO, privatePerms : true }, { _id : 3, name : MAN } 

Users:

 { _id : 111, name : Jesus, roleId : 1 }, { _id : 222, name : BatMan, roleId : 2 }, { _id : 333, name : Jack, roleId : 3 } 

When a user logs in and sends the user object back to the client, be sure to replace roleId with the corresponding role object from the database.

Switching to Node JS code:

Fully understanding your usecase, we can divide them into the following methods -

  • Createuser

  • CreateTodo

  • DeleteTodo

  • ReadTodo

  • UpdateTodo
  • CommentTodo

  • Assigntodo

Step by step, CreateUser .

Route code snippet:

 app.all('/users', users.requiresLogin); // Users Routes app.route('/users') .post(users.hasPerms('globalPerms'), users.create); 

In your controller, you can check based on the input globalPerms if the verified ones allow you to create a user by calling next() else return with the corresponding error message.

Now CreateTodo && & DeleteTodo :

Both of them pretty much work with the same logic with a little trick.

Route code snippet:

 app.all('/todos', users.requiresLogin); // Users Routes app.route('/todos') .post(users.hasPerms('globalPerms','privatePerms'), todos.create); .delete(users.hasPerms('globalPerms','privatePerms'), todos.delete); 

To create Todo, globalPerms have GOD and privatePerms with SUPER HERO , both of which can be enabled.

The todos.delete here will be in the todos.delete method, just make sure user.id === todos.createById else SUPER HERO can continue to delete Todos created by the GOD.

ReadTodo :

When a TODO is created, it must have createById , stored similarly, when someone is assigned a TODO , then assignedTo and assignedBy must also be written.

This simplifies the processing of many other operations.

user.role.globalPerms - provide GOD to all TODO data.

user.role.privatePerms - give TODO either created by him or assigned to him / her.

user.role.globalPerms === undefined && user.role.privatePerms === undefined - its MAN and give TODOs that are assigned to it only.

UpdateTodo and CommentTodo :

This is an exact copy of what ReadTODO DIY does.

Last, AssignTodo :

Simple, loggedInUser.id === todos.createdById , then he can assign it to anyone.

Two things to keep in mind here:

  • Since the purpose of the element mainly occurs on your UI (Angular) interface, I gave this approach of checking loggedInUser.id === todos.createdById . Any way recorded by the user will see all TODOs through a read operation and can assign it to anyone who likes it.

  • Make sure that SUPER HERO can only assign TODO to itself or another SUPER HERO or MAN, but not to the GOD. As you show Assign for options on the user interface, is beyond the scope of this question. It is just a head.

Hope this was clear.

NOTE. There was no need to grant permissions for MAN in roles, and we coped with all possible operations.

+5
source share

Possible approach-> have a role built into the user’s collection / schema: the user document should have the following:

 { _id : " email@mail.com ", name: "lorem ipsum", role: "MAN" } 

As far as your post is described, only God can create and designate TODOs. A role collection may contain the following:

 { _id : "MAN", globalPerm: [], privatePerm: [], assignedPerm: ["r","u"], }, { _id : "SUPER_HERO", globalPerm: [], privatePerm: ["c","r","u","d"], assignedPerm: ["c","r","u","d"], }, { _id : "GOD", globalPerm: ["c","r","u","d"], privatePerm: ["c","r","u","d"], assignedPerm: ["c","r","u","d"], } 

Node JS Middlewares Once you have the correct permissions for the user, you can use middlewares. An example of an express route for an HTTP request:

 app.post('/updateTodo', permissions.check('privatePerm', 'c'), function (req, res) { // do stuff 

};

permissions.check is called before the actual function body is executed to update TODO.

Therefore, if a user tries to update todo, he will first check the appropriate permissions.

0
source share

This is a very broad question that can be addressed in many ways.

You added that you are using the MEAN stack, so I will limit my question.

One thing that you have not included in the whole question is which authentication architecture you are using. Let's say you use token-based authentication, as a rule, people today use it.

We have 3 types of users. You have different options for distinguishing between the types of tokens.

  • Different collections (mongoDB) or Redis sets where they will be saved.
  • The encrypted token will be of the user type, etc. (this will be useful if you do not need to store tokens on the backend, you can simply decrypt and verify)

    • This will depend entirely on the use case.

Now, before allowing any user login to a specific user route, make sure you check the token first.

Example

 app.post('/godlevelroute', godtokencheck, callrouteandfunction); app.post('/superherolevelroute', superheroroute, callrouteandfunction); 

You have to send the token in the header from angular, and then you can extract the data from the header and then check if this particular user has permission to go this route or not.

Let them say that a god-level user is logged in, then he will have a divine voice with him, and we will first check this before allowing him to access this route, or you can simply show an error message.

This could be your test token check feature on the server.

 function checkToken(req, res, next) { var token = req.headers['accesstoken']; //access token from header //now depending upon which system you are following you can run a check }; 

Node Module Proposal: https://www.npmjs.com/package/jsonwebtoken

Now let's get down to the interface. You use angular depending on what you wrote, you can intercept the token before showing any page.

You can go through this blog to get an illustrative idea of ​​what I was trying to explain. Click here

0
source share

All Articles