How to Implement Scalable Multitenant Authorization | Cerbos
How to implement scalable multitenant authorization
Introduction
Building authorization for a software-as-a-service application often starts simple. With one customer or a handful of users, a basic role-based access control (RBAC) model might suffice. But as soon as you add that second customer - or the hundredth, or thousandth - things get complicated.
Hardcoding permission checks throughout your code becomes a nightmare to maintain. In a multitenant architecture, where many customers share the same application, scaling authorization logic presents unique challenges.
In this post, we’ll explore those challenges and how dynamic, tenant-aware authorization models can overcome the limitations of static RBAC. We'll cover common multitenancy patterns, the dreaded "role explosion" problem with traditional RBAC, and how to shift to tenant-aware roles and attribute-based access control (ABAC). We'll also discuss best practices like decoupling authorization logic from your application, externalizing decisions to a policy engine, and treating policy as code.
What makes multitenancy complex for authorization?
Multitenancy is fundamentally about multiple users or customer organizations sharing the same application infrastructure, with logical isolation between tenants. Different people have different access rights: the building owner or manager might have a master key to every unit, while a tenant only has keys to their own apartment.
In software terms, we need to enforce that kind of isolation and varying access levels through our authorization logic.
B2C account-based multitenancy
In business-to-consumer scenarios, a single account might contain sub-profiles or members. For example, Spotify allows family accounts where one subscription has multiple user profiles under it.
B2B organization-based multitenancy
In business-to-business SaaS, the tenant is often an organization or workspace. Applications like Slack illustrate this well. Slack has organizations (workspaces) that contain users, channels, messages, etc.
Hybrid models
Some applications mix individual and organization contexts. Zoom, for instance, allows personal accounts and organization accounts for businesses or teams.
The limits of static RBAC in a multitenant world
Most of us start with a straightforward role-based access control model. The crux of the issue is that global roles are too coarse-grained and inflexible for multitenancy. An "Editor" role might have broad meaning in your app, but in reality, a user might be an Editor in the context of Tenant A and just a Viewer in Tenant B.
The role explosion problem
Role explosion occurs when you proliferate roles to cover every combination of tenant and permission nuance. This leads to a number of headaches:
| Issue | Explanation |
|---|---|
| Management nightmare | The sheer number of roles becomes unmanageable. |
| Brittle, hard-coded logic | Tenant-specific roles often seep into authorization checks throughout your code. |
| Security and compliance risks | It's easy to make mistakes when a user has a long list of roles. |
| Static roles ignore context | A global role can't capture context-specific nuances. |
Tenant-aware roles
Instead of having one global role assignment per user, we shift to a tenant-aware authorization model. In a tenant-aware model, a user's permissions are always evaluated in the context of a specific tenant, project, or workspace. This means a user can have different roles in different tenants.
Going beyond roles with ABAC
ABAC uses attributes in addition to roles to define permissions more granularly. It allows for policies that evaluate attributes of the subject, the resource they want to access, and the action they're trying to perform.
Decoupling authorization logic from application code
Decoupling authorization checks from application code is a critical architectural decision in building scalable authorization. By externalizing authorization into a dedicated service, you simplify your application logic and ensure consistent enforcement of rules.
Treating authorization policy as code
Managing authorization policies as code enhances clarity and ensures that every change can be tracked through version control, reviewed, and tested. It provides an auditable history of how your authorization logic has evolved.
Balancing central control and tenant self-service
A layered approach to authorization allows central policies to enforce security while giving tenants flexibility to manage roles and permissions in their own context. This ensures the system remains secure while being user-friendly.
Key takeaways for scalable multitenant authorization
| Go tenant-aware | Move away from rigid global roles and embrace context-driven access control. | | Adopt attribute-based access control (ABAC) | Incorporate attributes into your authorization decisions for fine-grained control. | | Decouple authorization logic from application code | Externalize your authorization checks to a dedicated service to ensure consistency. | | Treat policy as code | Manage your authorization policies with the same discipline as application code. | | Enable tenant self-service safely | Allow tenants to manage their roles while maintaining central control over security. |
By implementing these practices, you'll have a clear, maintainable authorization layer that scales as your customer base grows. Dynamic authorization - combining tenant-aware roles and ABAC, enforced by an external policy engine - is key to scalable, secure multitenant SaaS.