Skip to main content

Role Based Access Control

Role based access control (or RBAC) is one of the most common authorization and access control schemes. With RBAC, the ability to access a resource or action in a system is tied to a permission (or policy), and each of those permissions is associated with one or more roles. Every user in the system has one or more roles and thus has all the permissions associated with those roles.

This hierarchical structure is fairly intuitive and works really well for managing user access in a wide range of applications such as SaaS & enterprise software, e-commerce websites, company internal apps, and more.

In this guide, we'll go over how you can use Warrant to build role based access control into an application.

Prerequisites

This guide exclusively uses the Warrant API and thus assumes you have a Warrant account with API keys. If you don't, please first follow the Getting Started guide to set up your account.

The 'Group' Object Type

Since RBAC is such a commonly used scheme, Warrant comes pre-configured with a group object type that you can use to implement it.

Each object of type group represents a distinct group (or role) within our application. For example, we might have an 'admin' group and an 'owners' group.

The group object type only has a member relation which allows us to associate users with a group. Putting all this together, we get the following simple object type definition for group:

{
"type": "group",
"relations": {
"member": {}
}
}

Managing Group Membership

One of the key capabilities we need around groups is the ability to add and remove users from them. With our group object type defined, associating a user with a group is as simple as creating a new warrant for that user that establishes the 'member' relation:

client
.createWarrant("group", "admin", "member", { userId: "user1" })
.then((newWarrant) => console.log(newWarrant))
.catch((error) => console.log(error));

Granting Permissions to Groups

In addition to managing group membership, we need the ability to grant specific permissions or scopes to groups. We can do this by creating warrants based on group. For example, let's say we have a 'feature' called 'query_builder'. We can grant all members of the 'admin' group access to this feature by creating this warrant:

// Grant all members of the 'admin' group access to 'query_builder'
client
.createWarrant("feature", "query_builder", "access", { objectType: "group", objectId: "admin", relation: "member" })
.then((newWarrant) => console.log(newWarrant))
.catch((error) => console.log(error));

Checking Permissions by 'Group'

In addition to managing group membership and granting permissions and scopes to groups, the last thing we need to be able to do in order to implement RBAC is enforcing access based on group permissions.

For example, let's say we have a user with id 'user1' that is part of the 'admin' group. Furthermore, we've defined a warrant in our system that grants all members of the 'admin' group access to the 'query_builder' feature. At runtime, the following check will resolve to Authorized given that 'user1' is a member of the 'admin' group which has access to the 'query_builder' feature:

client
.isAuthorized("feature", "query_builder", "access", "user1")
.then((isAuthorized) => {
if (isAuthorized) {
// 'user1' has access to 'query_builder'
}
})
.catch((error) => console.log(error));

Summary

In this guide, we showed how you can use Warrant to quickly implement role based access control in an application using the group object type. Group membership and group permissions can be managed via API or through the Warrant dashboard while runtime access checks can be used to gate access to data and features directly in your application.