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.
Express is a perfect choice for a server when it comes to creating and exposing APIs (e.g. REST API) to communicate as a client with your server application.
Create Tables
First you need to create your tables that will hold the associations between roles, permissions, and resources:
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.
Role rights in Node.js
Part 1:What is role and rights?
Role rights implementation is important part of any software.Role is a position of responsibility and every responsibility enjoys some rights given to them.There may be some common rights between few roles and some rights may strictly belong to specific role.
Rights are Urls that a role is authorised to access.It is thus necessary to create collection in db storing information of rights to a role. We have role collection schema as
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const RoleSchema = new Schema({ roleId:{ type:String, unique:true, required:[true,"Role Id required"] }, type:{ type:String, unique:true, required:[true,"Role type is required"] }, rights:[{ name: String, path: String, url: String }] }); module.exports = Role = mongoose.model('role',RoleSchema);
Now remember every role that is supose to exist is in Role collection and of above schema type.
In schema rights array of object we see the object has keys:
Thus if a user with role user has right to change username then he can hit url /users/set-username
.However a wanderer will not be able to access this url.A higher role like admin & superadmin should logically have access to all lower role rights(urls).
Role in real application are:-
Till Now we have understood what excatly is right and how it is mapped to a role.
Part 1.5:Registerd Urls/Config Urls
Here we have a file called registeredUrls.js which is like:
module.exports = { simple:{ "/":[""], '/users/':["login","register"], }, auth:{ //admin '/admin/': ['load-users' , 'set-new-password','delete-user'], '/teacher/':["add-teacher","delete-teacher","edit-teacher"], '/student/':["add-student","delete-student","edit-student","test-result"], //user '/test/':["view-test","submit-test"], '/profile/': ['change-username', 'update-profile-data', 'set-new-password', 'upload-pic', 'update-social-links'], '/teacher/':['load-teacher'], '/student/':['load-student'] } }
Similarly confgUrls.js
const configUrls= { '/roles/': ['get-rights', 'create', 'update-rights', 'load', 'delete', 'assign'] } module.exports = configUrls;
Part 2:Creating SuperAdmin
This is most essential part of application.Whenever server starts for first time or restart/reboot this step occurs.In config/init.js follow procedure:
At end of this function call we are always sure that we have a superadmin in application with all its sophisticated urls/rights initialised.
Part 3:Super-Admin-Specific-Urls
These are rights that are enjoyed by super admin only and must be maintained in seprate file in parallel to registerd url file.These include url rights which map routes used only by superadmin. Here we have routes to create role,load roles,get-rights for a roleId,update-rights for roleId/role type, assign-role to a user,delete a role.
For each user in code we need to change their role from guest to user(say after email verification).Or guest/user to admin by superadmin using assign-role url.Then updating admin rights using route update-rights.
The process ensure that every role has A collection Document and filled rights there.
Part 4:Authenticator Middleware
This heart of our RBACS logic.Here we use a middleware which follow process:
1. Fill all authentication required urls in a [AUTH_URLS] with auth-urls(registeredUrls.js) & super-admin-specific-urls(confgUrls.js) and simple url in different [SIMPLE_URLS].
2. Then check if (AUTH_URLS.indexOf(request.url) > -1){3rd step} else if (SIMPLE_URLS.indexOf(request.url)>-1){then it is public url so simple allow next()} else { response unknown url}
3. In this step we know that url being requested in AUTH_URLS thus required token check for authorization token header if found then extract token from it then{4th step}.if no authorization header found response "required token"/"unknown".
4. Token found, now verify that this token has a valid session.If yes {5th step} else token session not found login again. 5. validate jwt token verifying it if verified{6.step} else response "not valid jwt token".
6.till now correct url requested & token session exist & jwt valid token.Now using role-type information from session(stored in session is basic info of user and token) find in Role for this user session role-type thus we have its rights[].Now see if the request.url is included in rights[].if found {7th step} else {reponse "role not found/unknown user"}.
7. if found then {has access to this url next() } else { response "access denided"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With