Role rights in Node.js
Part 1:What is role and rights?
Role rights implementation is an 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 a few roles and some rights may strictly belong to a specific role.
Rights are Urls that a role is authorized to access. It is thus necessary to create a 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 supposed to exist is in Role collection and of above schema type.
In schema rights array of the object we see the object has keys:
- name(for the name of URL like “set-username”)
- path(for base path hit “/users/”)
- url(requested URL or complete path “/users/set-username”)
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:-
- Wanderer (Someone who is just visiting our site. He should be able to access all public routes. Simple URLs/Public URLs accessible to all thus need not make a separate role for this as it is not any authenticated right.)
- Guest (Someone who has registered but not verified say email not verified).
- User (Someone who has his verified email)
- Admin (Made an Admin by SuperAdmin after verifying.he enjoy most of the rights)
- Superadmin (Master of application.He enjoy some more sophisticated rights.More rights then admin)
Till now we have understood what exactly is right and how it is mapped to a role.
Part 1.5: Registered 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 the most essential part of the application. Whenever the server starts for the first time or restarts/reboots this step occurs. In config/init.js follow the procedure:
- Load All simple URLs(public) and Auth Urls(admin & users) & super-admin-specific URLs into superAdminRights[].
- Then run a function to create a user with role superadmin if doesn’t exist.
- Get a Role of type:”superadmin” if found:replace its rights with new rights(superAdminRights).else:create Role of type :”superadmin” and then fill its rights(superAdminRights).
At the end of this function call, we are always sure that we have a superadmin in application with all its sophisticated URLs/rights initialized.
Part 3:Super-Admin-Specific-URLs
These are rights that are enjoyed by super admin only and must be maintained in a separate file in parallel to the registered 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 the 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 ensures 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 follows the 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 a token check for authorization token header if found then extract the 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 the 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 denied”}