Every multi-tenant application needs to provide some level of access control. The most basic requirement would be that users can only access tenant/s they are members of. You should only be able to access your organization’s Jira tickets, or Slack channels, for example.
As multi-tenant applications scale, their requirements evolve and grow in complexity. This is especially true when they cater to large organizations and enterprises. These customers have unique use-cases that are not covered with the out-of-the-box roles you provide.
In this post, we describe how to satisfy these new requirements, while keeping your overall authorization system as simple as possible. Read on for all the details!
Multi-tenant RBAC
Role-based access control (RBAC) is a popular authorization model due to its simplicity. Permissions are grouped into roles that are assigned to users. Implementation is simple and straightforward: you define roles and map them to permissions. When a user tries to perform an action, you only need to check their role to decide whether access is granted or not.
RBAC has been around for a while and most applications have innate support for the concept of roles and groups. So it should come as no surprise that it is also popular among multi-tenant SaaS applications.
RBAC has one main drawback and that is that it relies on static roles. These roles have a set of fixed permissions that cannot be changed. And as new scenarios arise, the simplest solution tends to be to create new specific roles for those use-cases. This eventually leads to what is known as “role explosion,” where the sheer number of roles makes it virtually impossible to reason about access decisions, rendering the system ineffective.
Let’s look at an example: we have a CRM that uses traditional RBAC. It has “Admin,” “Editor,” and “Viewer” roles that have combinations of can-view
, can-edit
, and can-delete
permissions. Viewers have can-view
permissions, Editors are also granted can-edit
permissions, and Admins have all three. Most of your customers are content with this level of control over their CRM instance.
Some of your customers are asking for finer-grained controls. These requests tend to come from your larger accounts. One would like to provide their Finance team with access, limited only to the billing section, where they should have full privileges. Another is asking for the ability to create delegated admins (aka restricted admins). They have a new employee who is their “CRM admin.” They want him to have full control over the system, minus the ability to mass delete records.
You could create these very specific roles for your customers and hide them behind feature flags. And you will be tempted to do so. After all, it’s the easiest way to give them what they are asking for. But, you will ultimately bear the risk of role explosion and add unnecessary complexity to your authorization logic.
It’s also not what your customers really want. They don’t want you to create specific roles for them, because that will mean that they remain stuck in the same situation. The next time a new need arises they’ll need you to create that new role for them. They want a way to make RBAC dynamic. They want to be able to build their own custom roles.
Providing your customers with this ability is what you should want as well. Instead of building one off roles and managing an ever growing number of roles, you can provide a self-serve option for all your users to create custom roles.
Multi-tenant RBAC with custom roles
Keeping with our CRM example, Hubspot and Salesforce are both great examples of multi-tenant applications that use RBAC with custom roles. They allow customers to use a set of prebuilt roles that cover popular use-cases and are sufficient on their own for most customers.
The remaining use-cases are covered with the ability to create custom roles by selecting the exact privileges those roles will have over each of their services (i.e. CRM, marketing automation, sales tools, etc). This ability greatly reduces the disadvantage of using static roles in RBAC systems. It also introduces a new disadvantage.
Dynamic RBAC done right
Custom roles allow you to continue to provide your customers with a limited number of prebuilt roles that meet the requirements of most of them, plus one more “custom” role. You keep the number of roles in check and authorization logic tight, and your customers can self-serve to meet new use-cases as they arise.
Sounds good, right? Unfortunately, this method has two main drawbacks:Custom roles are still static
- Custom roles are still static roles. They include a set of permissions that cannot be changed. So the risk of role explosion is inevitable. True dynamic roles can be found in attribute-based access control (ABAC) systems. These systems use dynamic characteristics on the user-level (e.g. title, seniority), resource-level (e.g. owner, folder), or even environmental (e.g. device, network). ABAC authorization policies evaluate whether a user has access to a resource by dynamically evaluating these attributes. So instead of assigning users to roles, all you need to do to provide a user with custom access is to assign the right attributes.
- Multi-tenant RBAC require complex Rego policies. Supporting multi-tenant role-based access requires that we check whether a user has a role on a specific resource (in this case, a tenant). For this scenario, we need to write a complex policy that traverses a data structure that captures the relationship between users, roles, and specific tenants. This requirement might outweigh the simplicity of sticking to the RBAC model.
Alternatively, you can treat multi-tenant RBAC as a simple example of a relationship-based access control model (ReBAC). With ReBAC the relationships between objects and subjects determine access. We can then use a system like Topaz or Aserto with built-in functions that can evaluate relationships between subjects and objects in a fraction of the time and effort.
For example, a rule that needs to evaluate tenant membership can simply use the ds.check_relation
built-in:
allowed {
ds.check_relation({
"object": {
"key": input.resource.tenant,
"type": "tenant"
},
"relation": {
"object_type": "tenant",
"name" : "member"
},
"subject": {"id": input.user.id}
})
}
More about RBAC, ABAC, and ReBAC
Aserto makes it easy to add dynamic RBAC to your multi-tenant applications. Whether you opt to build custom roles into RBAC, implement ABAC and dynamic attributes instead of roles, or use a ReBAC to allow for the finest-grained control over your resources. It enables the simple evolution of your authorization model as requirements change.
Conclusion
RBAC is a popular authorization model due to its simplicity in logic and implementation. As a result, many multi-tenant applications provide their customers with role-based access controls.
As multi-tenant applications scale, customers start asking for specific roles based on their unique use-cases. The quickest way to deliver on their requests would be to build these specific roles for them and use feature flags to make sure the right role is available to the right customer. While this is the fastest way, it adds complexity to your authorization logic, and risks “role explosion.”
The right solution would be to allow customers to create custom roles from the set of available permissions. Instead of building 1:1 roles for customers, you’ll be building a useful feature for all your customers. And you’ll keep the number of roles you need to support minimal.
Custom roles are still static roles. To provide truly dynamic authorization you’ll need to use ABAC or ReBAC. ABAC allows for dynamic roles, and ReBAC allows for the fastest, finest-grained access.
We hope you’ve found this post helpful and would love to keep the conversation going. Drop us a line here, or join our community Slack.
Related Content
Implementing Custom Roles in your SaaS Application
Custom roles are tricky to implement. This post offers two approaches for allowing each tenant to add custom roles: one for simple RBAC, and one for fine-grained ReBAC.
Jun 20th, 2024
Authorization 101: Multi-tenant RBAC
Every multi-tenant B2B SaaS product needs an authorization model. The trick is to build one that can scale with your app.
Sep 9th, 2024
RBAC vs ABAC: pros, cons, and example policies
RBAC and ABAC are two popular models for securing access to resources. Both models have their merits and both have limitations. Learn all about role-based and attribute-based access control and see example policies in this post.
Jan 11th, 2023