Attribute-Based Access Control (ABAC) VS. Relationship-Based Access Control (ReBAC)
- Share:
Attribute-Based Access Control (ABAC) VS. Relationship-Based Access Control (ReBAC)
Every app out there needs an authorization layer, but choosing which authorization model to implement/build can be challenging. In this article, we will dive into two common authorization models - ABAC and ReBAC, discuss their pros and cons, and try to guide you in the decision of which one is right for your application.
Before we start, let’s cover some basics -
Intro: What is Authorization
Authorization is a complex challenge that basically every developer building an application has to face. It plays the crucial role of ensuring that the right people and services have the right access to the right resources.
It’s important to distinguish between Authorization and Authentication - Authentication handles who can log in to your application, while authorization handles what they can do once they are inside.
Application-level Authorization can be managed through different authorization models, and it’s up to developers to pick the most suitable authorization model for their application at each moment in time.
In this blog, we will explore and compare two commonly used models:
Attribute-Based Access Control (ABAC), and Relationship-Based Access Control (ReBAC).
You can also read our comparison between Relationship-Based Access Control (ReBAC)
and Role-Based Access Control (RBAC) here.
What is ABAC?
Attribute-Based Access Control (ABAC) is an authorization model where access control is determined based on conditions applied to attributes (or characteristics). This expands basic RBAC roles adding attributes into the mix, allowing the creation of much more granular authorization policies.
Here’s a rather simple example of an ABAC policy in plain English -
Employees based within the European Union can Edit Documents that are GDPR Protected.
In this example:
Employee is a Role
The location of the employee in the European Union is a User Attribute
Edit is the Action
Document is the Resource
GDPR Protected is the Resource Attribute
ABAC’s use of attributes allows the creation of very fine-grained authorization policies. Common attributes include (But are not limited to): Time, Location, Billing Status, and many more - all depending on the specific needs of your application.
Below is a simple example of an ABAC policy written in Rego, the policy language of Open Policy Agent (OPA). OPA is an open-source policy engine for controlling access to systems and resources. It allows separating policy logic from application code, enabling easy policy management and updates without requiring code changes or deployments.
package abac
# User attributes
user_attributes := {
"User1": {"location": "EU", "title": "employee"},
"User2": {"location": "US", "title": "employee"},
"User3": {"location": "EU", "title": "manager"}
}
# Document attributes
document_attributes := {
"Doc1": {"classification": "GDPR Protected"},
"Doc2": {"classification": "Non-sensitive"}
}
# Default deny
default allow = false
# EU employees can perform any action on GDPR Protected Document
allow {
# Lookup the user's attributes
user := user_attributes[input.user]
# Check that the user is an employee
user.title == "employee"
# Check that the employee is based in the EU
user.location == "EU"
# Check that the document is GDPR Protected
document_attributes[input.document].classification == "GDPR Protected"
}
# Allow any employee to access non-GDPR-protected documents
allow {
# Lookup the user's attributes
user := user_attributes[input.user]
# Check that the user is an employee
user.title == "employee"
# Lookup the document's attributes
document := document_attributes[input.document]
# Check that the document is not GDPR Protected
document.classification = "Non-sensitive"
}
To learn more about implementing ABAC with OPA’s Rego, check out this guide.
What is ReBAC?
Relationship-Based Access Control (ReBAC) is a policy model focused exclusively on the relationships, or how resources and identities (aka users) are connected to each other and between themselves. The consideration of these relationships allows us to create authorization policies for hierarchical structures.
ReBAC allows us to derive authorization policies based on existing application-level relationships. Put in the simplest way, it allows us to create a policy like this:
A user who is the Owner of a folder will also get Owner access to every file within that folder.
Creating policies based on relationships, rather than roles or attributes, saves us from having to create authorization policies on a per-instance basis.
To create ReBAC policies, we need to create roles specific to a given resource. This means that the role, and the permissions it carries, are only relevant in the context of that specific resource. A resource role is commonly denoted as Resource#Role.
The most common relationship types ReBAC allows us to handle include:
Parent-child hierarchies - relationships where resources are nested under other resources. This allows us to create a policy such as:
A user who is assigned the role of an Owner on a folder will also get the Owner role on every file within that folder.
We can see that the user's access to the files is derived from the combination of two elements: The nesting of the files within the folder, and their role on the folder.
Organizations - relationships based on grouping together users. This allows us to create a policy like:
A user who is assigned the role of Member on RnD Team will also be assigned the role of Editor on a File when the RnD Team is the Parent of a File.
Putting several users in one group allows us to derive policies based on their group membership instead of per individual user.
Here’s a simple example of ReBAC in Rego:
# return a full graph mapping of each subject to the object it has reference to
full_graph[subject] := ref_object {
some subject, object_instance in object.union_n([files, teams,organizations])
# get the parent_id the subject is referring
ref_object := [object.get(object_instance, “parent_id”, null)]
}
# … see full Rego code at https://play.openpolicyagent.org/p/4qkNc0GtPP
# rule to return a list of allowed assignments
allowing_assignments[assignment] {
# iterate the user assignments
some assignment in input_user.assignments
# check that the required action from the input is allowed by the current role
input.action in data.roles[assignment.role].grants
# check that the required resource from the input is reachable in the graph
# by the current team
assignment.resource in graph.reachable(full_graph, {input.resource})
}
The full rego code for this example is available in the OPA Playground. For more information about implementing ReBAC with OPA, check out this guide.
ABAC vs. ReBAC: Pros and Cons
ABAC | ReBAC | |
Use case | ABAC allows the creation of fine-grained policies based on user and resource attributes, significantly extending upon basic RBAC. | ReBAC is designed to represent hierarchies and nested relationships, making it the most suitable choice for managing permissions for complex hierarchical relationships. |
Representation of Relationships | Can be cumbersome and verbose when managing access to hierarchical structures where the nesting of resources under other resources is present. | Excellent for representing hierarchies and nested relationships |
Reverse Indices (who has access to y, instead of does x have access to y) | Implementing reverse indices is very difficult | Naturally supports reverse indices (Thanks to ReBAC’s graph-like nature). |
Performance | Often provides better query performance but can be heavier on data mapping and loading. | Data mapping is usually easier, but the recursive nature of relationships can produce inefficient queries. |
Homebrew-Implementation Complexity | Medium complexity compared to other models* | Highly complex |
Granularity | Extremely high level of granularity | Higher granularity than RBAC, not as granular as ABAC** |
Policy definition | Permissions can be defined en masse instead of individually for every single resource by using teams and groups. They can also be added/removed from an application without requiring complex data migrations (e.g., adding/removing permissions for each individual user record)*** | |
Auditing difficulty | More complex than RBAC, yet still easily auditable if set up correctly. | The complexity and recursive nature of ReBAC policies can make auditing challenging. |
* While less complicated than ReBAC, ABAC can still be quite challenging to implement, especially in large and complex applications that require support for a large number of roles, users, and attributes. When designing and implementing ABAC it is crucial to follow established best practices.
**Though much more granular than RBAC, ReBAC still struggles with truly fine-grained, or dynamic permissions - such as rules dependent on dynamic attributes like time, location, and quotas.
***The challenge of getting all the relevant attribute data into your decision point in time can be daunting (though tools like OPAL can elevate this).
Making the choice: ABAC vs. ReBAC
ReBAC’s role derivation allows us to construct authorization policies that are far more efficient for hierarchies than ABAC.
Take the following example:
Say we want to grant user Bob access to his files based on his ownership of them.
Using ABAC, we would add an “Owner” attribute to each of the files and folders, and grant Bob a role that allows him to access all files and folders in which an “Owner” attribute references Bob’s ID.
ReBAC allows us to avoid that by leveraging existing application-level relationships and creating simple policies based on hierarchies and groupings.
(Yes, we could implement the attribute of ownership on the files to point to `Bob’s files` instead of to Bob, and recursively check if `Bob’s files` are connected to Bob - but that would basically be implementing ReBAC on top of ABAC.)
On the other hand, ABAC allows us to create far more granular rules by using attributes than ReBAC.
At the end of the day, authorization models are more thinking tools than concrete guidelines, and most applications end up mixing between them (especially as time passes and the applications evolve). The most important thing is how you design them so that they're flexible, scalable, and continue to evolve along with your application's needs.
Flexible, Scalable Implementation
Setting up and managing complex authorization frameworks like RBAC, ABAC, or ReBAC can pose a challenge for developers and other stakeholders, potentially leading to bottlenecks in the process. On top of that, as the requirements of your application change, there may be a need to quickly transition away from basic authorization methods such as ACLs, potentially causing delays that could take months to resolve.
The work you put into implementing an authorization layer doesn’t end at the point of implementation either - as creating additional roles, attributes, and policies requires complex R&D work and steep learning curves.
Why not both?
The solution is implementing and managing your RBAC, ABAC, or ReBAC policies using an authorization service that allows for flexible transition between authorization models and provides a simple API and no-code UI that makes permission management accessible to all stakeholders.
That’s where Permit comes in -
Permit.io: RBAC, ABAC, and ReBAC with a no-code UI
Permit provides developers with a permission management solution that allows for both smooth transitioning between RBAC, ABAC, or ReBAC without any changes to your application code, and the ability to create and manage policies using an accessible no-code UI.
Permit’s UI allows us to define our required roles, attributes, and role derivation logic, generates code for us, and pushes any updates or changes to our application in real time. Implementing authorization with Permit ensures everyone is included in the permission management process, preventing developers from becoming bottlenecks.
Want to learn more about Authorization? Join our Slack community, where there are hundreds of devs building and implementing authorization.
Written by
Daniel Bass
Application authorization enthusiast with years of experience as a customer engineer, technical writing, and open-source community advocacy. Comunity Manager, Dev. Convention Extrovert and Meme Enthusiast.