Managing who can do what in an application is a fundamental challenge for developers. As your app becomes more complex and your user base grows, manually assigning permissions to every user becomes unmanageable and error-prone. Role-Based Access Control (RBAC) solves this by grouping permissions into roles and assigning roles to users.
RBAC is one of the most widely used access control models. It enforces the principle of least privilege, simplifies admin tasks, and improves auditability.
But "RBAC" isn't a single, monolithic concept. It's a spectrum of models, each suited for different needs. Choosing the right one is critical for building a secure and scalable application.
What we'll cover
- RBAC Foundations: Core concepts and structure
- Hierarchical RBAC: Role inheritance and org charts
- Resource-Specific Roles: Per-resource roles for granular control
- Choosing the Right Model: When to use which
- RBAC Alternatives: ReBAC, ABAC and beyond
RBAC Foundations
Every RBAC system has three core components:
-
Users: The individuals using your app (e.g.,
Alice
,Bob
). -
Roles: Job functions or titles that group permissions (e.g.,
editor
,viewer
). -
Permissions: Actions roles can perform (e.g.,
read_document
,edit_document
).
In this model, you define a set of roles and the permissions associated with each. Then, you simply assign one or more roles to each user. For example, in a content management system, you might have:
- A
writer
role withcreate_post
andedit_own_post
permissions. - An
editor
role withedit_any_post
andpublish_post
permissions.
If you assign the writer
role to Alice, she can create new posts and edit the ones she created, but she can't publish them or edit Bob's posts. This is simple, predictable, and easier to manage than assigning individual permissions to Alice directly.
Hierarchical RBAC: Mirroring Your Org Chart
RBAC as described above works well for simple structures, but what happens when your organization has a clear chain of command? You wouldn't want to manually assign a manager all the same permissions as their direct reports, plus their own. That's where Hierarchical RBAC comes in.
Hierarchical RBAC introduces the concept of role inheritance. It allows you to create a hierarchy where senior roles automatically inherit all the permissions of their subordinate roles.
For instance, you could structure your roles like this: Admin
→ Editor
→ Writer
- The
Writer
role has base-level permissions to create and edit their own content. - The
Editor
role inherits allWriter
permissions and adds the ability to edit any content and publish it. - The
Admin
role inherits allEditor
permissions (and by extension,Writer
permissions) and adds user management capabilities.
This model is efficient for organizations with well-defined structures. It reduces redundant configuration and ensures that access levels naturally align with organizational responsibility. When a new permission is added to the Writer
role, Editors
and Admins
get it automatically, without any extra work.
Beyond the Basics: Resource-Specific
So far we have discussed organizational roles. A user is an editor
or an admin
across the entire application. But modern applications, especially collaborative SaaS products, often require more granular control.
What if a user is an admin
for one project but only a viewer
for another? This is where Resource-Specific Roles come into play.
In this model, a role is not just assigned to a user; it's a relationship between a user and a specific resource. For example, in platforms like Google Docs or GitHub, you don't have a single "editor" role for the entire platform. Instead, you are granted the editor
role on a specific document or the maintainer
role on a specific repository.
This is a powerful and flexible model, but it also introduces complexity that can be challenging to build and manage from scratch. The number of relationships between users, roles, and resources can increase significantly, making it difficult to reason about your authorization logic.
This is where an authorization service like Oso becomes valuable. Oso is designed to handle these complex, fine-grained models. Its declarative policy language, Polar, allows you to define these relationships naturally.
For example, here’s how you could define a resource-specific role in an Oso policy:
actor User { }
resource Organization {
roles = ["admin", "member"];
permissions = [
"read", "add_member", "repository.create",
"repository.read", "repository.delete"
];
# role hierarchy:
# admins inherit all member permissions
"member" if "admin";
# org-level permissions
"read" if "member";
"add_member" if "admin";
# permission to create a repository
# in the organization
"repository.create" if "admin";
# permissions on child resources
"repository.read" if "member";
"repository.delete" if "admin";
}
This policy defines an authorization model where a User
can have roles within an organization
, such as "admin" or "member", with a role hierarchy granting admins all member permissions. It specifies both organization-level and child resource permissions (like for repositories), determining what actions each role can perform. Oso's engine evaluates these rules efficiently, returning authorization decisions in under 10ms.
Choosing and Implementing the Right Model
So, which RBAC model is right for you? The answer depends entirely on your application's needs.
Here’s a quick guide to help you decide:
Model | Key Feature | Best for |
---|---|---|
Foundational RBAC | Simple role-to-permission mapping | Small applications, internal tools, or systems with a few, well-defined user types. |
Hierarchical RBAC | Roles inherit permissions from others | Applications for organizations with clear reporting lines or structures. |
Resource-Specific RBAC | Roles are tied to specific resources | Collaborative SaaS, multi-tenant applications, and platforms with user-generated content. |
RBAC Alternatives
RBAC works for many apps—but it doesn’t scale indefinitely. Most teams eventually hit one of these problems:
- Role explosion: You create new roles to satisfy each scenario, making it difficult to manage and complex to audit.
- Over-permissioning: To avoid role explosion, you consolidate permissions into fewer roles, accepting the risk that some users may be over-permissioned.
At that point, other models may be a better fit:
- Relationship Based Access Control (ReBAC) - organizing permissions based on relationships between resources, such as a user can edit a task if they are a collaborator on the project the task belongs to
- Attribute Based Access Control (ABAC) - a superset of RBAC and ReBAC, the ABAC model organizes permissions based on user, resource, or context attributes. An example might be a finance manager can only access a report during business hours from their company laptop.
To learn more about these models, I recommend that you check out Authorization Academy. It’s a series of technical, vendor-agnostic guides on application authorization. There is also a great comparison of RBAC vs ABAC available on the Oso website with examples.
Top comments (4)
big fan of the authorization academy!
really nice overview of RBAC, easily misunderstood topic
Great write up!
Super clear breakdown of the core RBAC patterns, plus a great resource for folks starting to design their own model!