A few days ago, some of my colleagues approached me regarding an issue with an Open Source application called Makaut Buddy which is a notes-sharing platform designed for our university, aimed at helping students share top notes, past exam questions, and YouTube tutorials efficiently.
While they had successfully developed a system for uploading resources, they encountered a challenge in ensuring that only authorized individuals could upload content.
As shown in the demo below, any user could create a resource after signing up. This posed a big problem because we could not regulate what users upload, some might’ve even uploaded harmful or disturbing content.
Initially, they defined an Admin role and granted a select group of individuals administrative privileges. However, as the number of roles increased, the code became increasingly complex and difficult to manage.
This is when I had the idea to write this article to raise awareness about efficient ways of managing authorization using a Role-Based Access Control (RBAC) model with the help of third-party authorization tools like Permit.
In addition to implementing RBAC, we also introduced a Request Access Approval system. This system ensures that any user who wants to upload content must first request access, which an admin can then approve or deny. This added layer of security helps us maintain the integrity of the content on Makaut Buddy.
In this article, I have used JavaScript as the programming language and Next.js as the framework. However, the concepts discussed here are not language-specific, and you can implement them in your preferred programming language.
By the end of this article, you will know to implement a basic RBAC model in your application.
With that said, let’s dive in!
Remember those mornings rushing to school? The security guard checking your ID is a perfect example of authentication. They're verifying your identity as a student allowed on campus. But that's just the first step. Even after being identified, you wouldn't just walk into any classroom, right? That's where authorization comes in.
Think of your class schedule as your authorization. It grants you access to specific areas (classrooms) based on your role (student enrolled in that class). You wouldn't be authorized to enter the teacher's lounge or the library's restricted section – even though you're a student (authenticated).
The difference between Authentication and Authorization is like asking “Who are you?” vs “What are you allowed to do?”
Authorization is important in every organization as it prevents individuals from performing actions they are not authorized to do. This ensures the safety of the organization and helps prevent losses.
Let’s illustrate the above statement with an example:
In a company, there are some senior engineers with deep experience and some interns still learning the ropes. You can imagine the disaster it would cause if both the senior engineer and the intern had the same level of permissions. The interns who are still learning might unknowingly make some mistake for which the company will have to pay. In situations like these, the Role Based Access Control Model works the best because the permissions are not assigned to individuals instead the permissions are assigned to roles. For instance, only a senior engineer or tech lead can Delete Resources whereas all interns can only view and manage resources.
Next, let’s see how we can implement RBAC in an application.
First, we need to define roles and assign permissions to each role.
Note: A Role is the position or purpose that someone has in a organization, we need roles so that we can differentiate between individuals based on the permissions or privileges assigned to that role.
We need a way to assign a role to each user of the application. This is generally done after the user signs up.
We need an API in our backend that takes in the operation a user wants to perform and checks the user's authorization. The diagram below will give you a better understanding:
However, we are not going to implement the entire model from scratch. Instead, we are going to use a third-party authorization tool called Permit which will make the whole process of establishing authorization very smooth and efficient for us, so that you can work on the features that really matter.
The below diagram shows you how we are going to leverage Permit to implement RBAC in our applications:
In this section, we will walk through the steps to implement Role-Based Access Control (RBAC) using Permit.
As we are using a Permit for establishing an RBAC model, first we need to create a Permit account and a workspace :
Now we need to create a Resource which is the entity we want to control access to in our application.
For example, in a note-taking application, the resource would be Notes, and the actions could be Create, Read, Update, and Delete.
To create a resource:
In the example above, the Resource name is Notes and the actions that the user is allowed to perform are Create, Read, Update, and Delete.
After creating the Resource, we have to define the roles that are going to exist in our application.
In this case, as the application is a note-sharing application for a university, the roles are going to be:
Once we have created both roles, we now have to assign the actions that each role can perform from our policy editor, as shown below:
Now that your Permit account is configured, you can start creating the backend APIs to communicate with Permit. We will use the Node.js SDK provided by Permit. You can find the SDK for your preferred programming language in the Permit Documentation.
Sync Users and Assign Default Role
First, we need to make sure that each user that signs up in our application is synced to the permit directory and assigned a default role of Student.
To do this we need to create a backend API as shown below:
This API does 2 things:
createUser
API.assignRole
API.
You can read more about all the APIs that Permit provides at permit docs
Get User Role
Next, we need to create a backend API that gets the role of the user from Permit.io and sends it back to the frontend .
The API shown below gets the user using the permit.api.users.get(user_key)
This API gets the user role with which we can manipulate our front-end components to allow only the people having special roles to be able to see it.
You can also check out the permit.check() function to verify if a user with a certain role is permitted to perform an operation.
With this, we have successfully implemented an RBAC model using Permit. Now, we can integrate the backend routes with the frontend framework or library of your choice to complete the setup.
To complete our setup, we need a component that allows users to request role upgrades:
Permit Elements are a part of “Permit Share-If” which is a suite of prebuilt, embeddable UI components that make access sharing in applications a breeze. Designed to provide fully functional access control, they make delegating permission management to your users simple and safe.
That’s it we’ve created the elements.
Before using the elements, we need to create a backend API for logging in the user to the permit element,
Note: It's important to log in the user as early as possible, preferably right after signup.
Now, let’s look at the code:
API code serving at endpoint /api/v1/login_permit/?userkey=user_key
:
The frontend code for implementing login will look like this:
That’s it we’ve set up our code.
Now, we just need to go over to the permit dashboard and copy both the user management iframe and access-request iframe, as shown below:
Now once we’ve got the code, we need to add the iframe
to our frontend where we want to show the elements to our users, we need to:
With this, we have successfully set up an access approval system where users can request role upgrades, and admins can approve or deny these requests.
This demo shows how a user with the "Admin" role can access the upload widget
This demo illustrates how a user with the "Student" role cannot see the upload widget and can request an upgrade to the "Admin" role:
This demo shows how privileged users can approve role upgrade requests:
This demo demonstrates how a user, after being upgraded from "Student" to "Admin," gains access to the upload widget
That’s it!
Thank you for reading this far.
In this tutorial, we explored authorization and understood why authorization is very important in any application. We also looked at how we can set up and configure Permit to secure the application and control user access based on their roles.
This article is just the tip of the iceberg of authorization and the RBAC model. You can look into ABAC and ReBAC for more fine-grained Authorization.