Implementing Role-Based Access Control with Warrant and Postman
This is a guest post written by Aditya Kajla, co-founder and CEO at Warrant.
If you’ve used a SaaS application, particularly one that handles sensitive data—like application logs, finances, or HR data—chances are you’re familiar with role-based access control (RBAC). It is one of the most widely used access control schemes in B2B and SaaS applications. With RBAC, each user is assigned one or more roles based on their role(s) within the application and/or some larger organizational structure. In turn, each role is assigned a set of permissions that define exactly what users with that role can see and do within the application. This intersection of roles and permissions makes it easy to group users and control their application permissions.
Now, before we go any further, a quick refresher on the two halves of the auth equation: authentication and authorization. While authentication (authn) is purely focused on identity (who you are), authorization (authz) is all about what you can do in a system and is closely related to an application’s domain and data. Even though RBAC is one of the most common authz schemes, there are many others, including attribute-based access control (ABAC) and relationship-based access control (ReBAC), to name a few.
Like authn, it’s important to implement proper authz in order to prevent improper access of data including dangerous security vulnerabilities like insecure direct object reference (IDOR). In fact, the severity of authz vulnerabilities and the explosion of SaaS software over the past decade have led to OWASP rating broken access control as #1 on its latest “Top 10 Web Application Security Risks” list.
For most SaaS applications, implementing even basic RBAC can go a long way towards mitigating critical authz risks. In fact, most apps start off by implementing some form of RBAC before moving onto more sophisticated and finer-grained authorization schemes that are tied down closer to the data domain.
At Warrant, we’ve built application authorization as a service. We help developers at companies of all sizes set up, manage, and enforce their authorization models, from basic RBAC to resource-based fine-grained authorization, all without having to build and maintain their own infrastructure. In this post, we’ll go over how you can quickly implement RBAC in your SaaS/B2B application using Warrant. You can follow along with the example scenario using our Warrant collection in Postman.
Example RBAC scenario
For our example, we’ll implement RBAC within a simple reporting application. This application has three roles: Owner, Executive, and Team Member. With Warrant, you can actually create your own roles and permissions using any name, such as
edit_reports. An Owner is the most privileged role and has the following permissions:
delete_users—whereas the Executive role can
view_reports, and a Team Member can only
view_reports. Here’s a full breakdown of the roles and permissions:
- Team Member
At a high level, implementing RBAC requires defining three key objects: roles, permissions, and users. RBAC works well with a small set of well-defined roles. For example, our application has Owner, Executive, and Team Member roles.
Similar to roles, the set of all permissions should be finite and well defined, although there may be many more permissions than roles. Permissions can imply behaviors on specific types of objects. For example, our application has permissions such as
With roles and permissions defined, we can then assign specific permissions to roles and then assign roles to specific users. Once all of these mappings are defined, we can check permissions for specific users in our application at runtime. For example, we can ask if
user1, who is an Owner, can
create_reports. Given that Owners can
create_reports, our permission check would return true.
With Warrant, all of this (definition of roles, permissions, users, and enforcement at runtime) can be done via API and from the Warrant dashboard. We’ll go over some examples of how to set up and enforce RBAC using our Postman API collection as a reference.
1. Create a Warrant account and get API keys
In order to use Warrant and make API requests, you’ll first need to create a Warrant account here. Once you have your API keys, you can follow along with the examples below.
2. Creating roles
Once you have an API key, you can start making API requests to Warrant. The first thing to do is create roles using the Roles API. For example, we can create the
owner role with the following request from our Postman Collection:
3. Creating permissions
After creating our roles, we need to create each of the permissions. For example, we’ll create the
create_report permission using the Permissions API:
4. Assigning permissions to roles
Now that our roles and permissions are defined, we need to assign permissions to roles as per the model we described above. For example, we need to assign the
create_report permission to the Owner role:
5. Assigning roles to users
With our roles and permissions ready to go, the last step is to assign roles to specific users. Let’s say we already have a user tracked by Warrant with userId =
user1 that we’d like to grant an Owner role. We can assign this role to the user through this API call:
6. Enforcing RBAC in our app
With our RBAC model completely defined, we’re now ready to start enforcing permission checks in our application. For example, we might want to add a
create_report permission check in our application’s
Checking permissions on the frontend
These permission checks are intended to happen on the backend but sometimes that’s not enough. In addition to checking for the
create_report permission on the server before serving the request, we might want to hide the Create Report button in our frontend web app to ensure that users without the
create_report permission don’t see the Create Report button in the first place. Warrant has convenient drop-in React and Vue.js wrapper components that easily make UIs “permission-aware” for exactly this use case. Although we won’t go into more detail here, our docs can help you get set up with these frontend components.
What’s next? The Holy Grail of fine-grained authorization
We’re finally done! Or are we? RBAC is widely used and popular, particularly due to its simplicity and the ability to express permissions based on organizational hierarchies (common in most companies). However, there are times when apps need more fine-grained access control that can’t easily be expressed in an RBAC or even ABAC-type model.
Let’s go back to our reporting application example. With our RBAC setup, we have a good way of granting permissions to specific groups of users (e.g., creating and editing reports). But what if we wanted to grant a specific user (say, ‘user1’) the ability to edit one specific report (e.g., the report with id = ‘a87sljb23’) but no others? Our RBAC model isn’t specific enough to easily express these types of resource-based policies or rules.
These fine-grained rules require more than just role and permission associations. Specifically, such rules are typically a combination of three parts: a user, relation/action, and object. In our report example, the user is
user1, the relation/action is
editor and the object is
report a87sljb23. Enforcing these types of policies requires tracking them for many different combinations of users and objects in the system, which isn’t trivial.
Fine-grained authorization policies like these are becoming more common, especially as apps add more collaborative features and user-generated content while having to comply with more thorough regulations like CCPA and GDPR. We’ve built Warrant to handle these types of fine-grained authorization requirements in addition to basic RBAC. So if you find yourself having to solve for fine-grained permissions, get in touch with us.
Technical review by Ian Douglas.