Role Based Access Control, secure and correct way?

When doing role based access control/user access control on nodejs/expressjs web application do I just create a middleware and use the if statement in the middleware to check whether or not the user who is accessing the route has certain role?
Something like this:

const roleCheckMiddleware = (req, res, next) => {

  if(req.user.permission === 'user'){
    
    if(/*Check other things*/){
      /* next */
    }else{
      /* return unauthorized */
    }
    
  }else if(req.user.permission === 'admin'){
    
    if(/*Check other things*/){
      /* next */
    }else{
      /* return unauthorized */
    }
    
  }else if(req.user.permission === 'super admin') {
    /* next */     
  }else{
    /* return unauthorized */
  }
};

app.delete('/account/:acountId', roleCheckMiddleware,() => {
  /* Delete account */
});

Is this the secure/correct/recommended way to apply role based access control/user access control on nodejs/expressjs web application? Or am I doing it wrong?

I know I can use a role based access control/user access control nodejs library to do it but the main reason I don’t want to use a library is because I want to learn/understand how to apply this kind of functionality to my web application and also I only have three roles.

1 Like

Hey @Mr.Rdcti186h,

One solution is to use Cookie Based authentication, where the server will create a user session and id, and store it inside a database along with the user’s role in the database. Then when the user wants to access something, just get their user-specific id and session and check for authenticity. If it’s legit, then you can proceed to find the information about the user in the database using the user info and retrieve information about the user’s role. If the user has the permission, then execute, else return unauthorized. This can be achieved using express’ session-id and passport middleware.

Another way is to use token based authentication, but I do not really know exactly how it works, other than it authenticates in the server instead of the client. You can definitely search it up.

Here’s a good video you can refer to about session and token authentication:
Session vs Token Authentication in 100 Seconds - YouTube

Hello there,

This is difficult to answer as is. @Catalactics shared some common, and useful, resources for authenticating a user. And using those libraries is the recommended approach, unless you are writing your own library - kudos for learning by doing from scratch, though.

I am not an expert on security, and have always used libraries to meet security/authentication requirements. So, take this with a pinch of salt.

An issue you might experience with your current method is:
A) When are you setting/giving a user their role/permission?
B) How are you associating a user with this role?

That is to say, what is preventing a user from defining their own role, regardless of permissions. So, the security comes in play when we consider where user.permission is set/stored.

Simply, I might expect a user’s role to be stored in the database, and retrieved from there, and a user can be given a new role by a user in the database with permission to write to it.

I hope that makes some sense.

P.S. I would think it a confusing naming convension seeing permission where you do actually mean role. I expect permission to be an object with bool-type logic (e.g. { canAccessAdminPage: true, canWriteToDB: true... })

1 Like

Hi, @Sky020
But to implement this kind of role based access control/user access control am I on the right track, I mean to use middleware and inside of middleware use if statement to check user’s role.

(I am using JWT Token so the req.user.permission/req.user.role is from the payload which I set it to req.user after I verify and decoded the token)

Hi,

you maybe want to check out my example of how to use React, Express and jsonwebtoken to check if a user is authorized to access a route or not. I use the localStorage to save the token.

https://forum.freecodecamp.org/t/react-express-authentication-by-jsonwebtoken-jwt-example/434717

Best regards,
Thorsten

In general, yes, you are on the right track. The only thing I can say is to keep your code as DRY as possible - if you have a lot of if...else logic, there may be room for improvement. Otherwise, if that is all of the roles you have/are going to have, then it does not matter too much.

Remember this is authorization not authentication so I’m assuming you already have a way to authenticate a user securely. If not, start there.

The security concern I see here is that it looks like your grabbing the permission off the user from the request. That means a user could just modify the payload and give themselves super admin privileges :sunglasses::computer:.

If you’re using cookies for user sessions, you’ll want to read the permissions from the database. If you’re using JWT the permissions can be embedded in your signed token which has to be validated first before you check permissions.

Bottom line is that the data you use to check the role or permissions of the user absolutely can never come from the request body. A cardinal rule in software development is never trust the user.

There are a lot of ways to implement ACL. The best way to learn is go look at libraries that do it and read their docs/source code.

Of course it’s fun to write your own too.

What I see wrong with your middleware is it’s unclear how it would get used. Typically you want the ability to guard a specific endpoint or group of endpoints with a middleware that meets a specific criteria such as being an admin role for example.

I would split your middleware up into one per role. So I would have an isAdminMiddleware that only checks if the authenticated user is an admin. Then all your admin routes can be in a group that’s protected by that middleware.

It makes much more difficult to accidently add an admin route that doesn’t get protected.

Also a side note, ‘user’, ‘admin’ and ‘super admin’ are usually considered to be “roles” in classic ACL. A permission would be something like ‘can edit posts’ or ‘can read comments’ etc.

Cheers!

So basically the way I am implementing role based access control/user access control is correct(using middleware and inside of middleware use if statement to check user’s role) but I need to watch out where I am grabbing the user’s role to do the check and I need to refactor my code, so it is less repetitive.

Currently, I only have this three roles but some day if I need to create a role based access control/user access control web application with a lot of roles(example: 5 roles or more) should I still using this kind of approach cause if I do, I’ll probably need a lot of middlewares with a lot of checking(if statements) or is there a better approach?