Relationship Based Access Control (ReBAC): When To Use It
Tags: webdev, programming, security, tutorial
Published: 2024-01-18 13:37:53

Relationship Based Access Control (ReBAC) has gained its popularity over years among startups to large enterprises. Yet, some large tech companies are already starting to use ReBAC as their leading access control model.

One of the biggest contributions to the popularity of ReBAC is definitely the Zanzibar whitepaper. [In 2019 Google published whitepaper](https://research.google/pubs/zanzibar-googles-consistent-global-authorization-system/) of its relationship based global authorization system called Zanzibar, which handles authorization for YouTube, Drive, Google Cloud and all of Google’s other products.

In a short time Zanzibar - correlatively ReBAC - gained attention quickly. In fact some companies like [Airbnb](https://medium.com/airbnb-engineering/himeji-a-scalable-centralized-system-for-authorization-at-airbnb-341664924574) and [Carta](https://medium.com/building-carta/authz-cartas-highly-scalable-permissions-system-782a7f2c840f) started to shift their legacy authorization structure to Zanzibar & ReBAC style systems.

Additional to shifts from large tech companies, ReBAC based solutions increased over the time. We're also one of them, building an [open source authorization service](https://github.com/Permify/permify) that builds its core on top of ReBAC and Google Zanzibar.

Although ReBAC is best known for social networks due to its core concept being about the network of relations, it can be applied beyond that.

Unfortunately, we’re seeing a significant number of businesses still trying to implement ReBAC-type permissions by using Role Based Access Control (RBAC) or Attribute Based Access Control (ABAC) models, which creates a huge technical debt and leads to security breaches over time.

In this post, we’ll focus on common usages of ReBAC and cover three highly-used models of ReBAC that you shouldn’t try to implement with RBAC or ABAC.

- Ownership
- Parent-Child & Hierarchies
- User Groups & Teams

But before diving in, let’s start with a quick intro about relationship-based access control and cover how it works.

## What is Relationship Based Access Control ?
ReBAC is an access control model that defines permissions based on the relationships between entities and subjects of your system.

If we think of a simple document storage system, similar to Google Drive, which typically allows doc creators (or owners) to edit or delete the documents, which ensures that no ordinary user can make updates on a random resource.

![relations](https://github.com/Permify/permify/assets/34595361/4b15471b-05aa-4633-9721-c45161cd7bea)

In our document storage system, the **Creator** represents a relationship between the user (the subject) and the document (the entity). Therefore, if user X has a creator (owner) relationship with document Y (which means user X created the doc Y), then the system allows user X to edit or delete document Y without the need to explicitly define the 'editor' role.

Subject indicates the party that takes the action on resources. In most cases - likewise in this example - the subject will be a user, but it can also be another entity like a device, tenant or user set such as team members. 

We’ll cover all these use cases, but since we started with creator - which is a form of ownership - let's continue with it and introduce our first ReBAC model: **Ownership**.

## Common ReBAC Models

### Ownership
Ownership can occur in many places across different applications. The general idea is, users or entities have absolute permissions on their own data. 

Such examples are; users accessing their own profile settings in an application, tracking their own healthcare data, or viewing their own governmental information.

We mentioned the example **“Users can edit posts they created”**. We can easily achieve this functionality with ReBAC. 

The biggest advantage of using relationship-based access control is that you can often utilize data already present in the application.

What I mean is that many applications already operate with a database containing a network of entities that have relationships with each other. We can clearly see this in relationship databases. 

![ownership](https://user-images.githubusercontent.com/34595361/213843053-74ac060c-b051-418d-9556-b99cccb12420.png)

As an example from a simple blog application, when a user creates a post you can store its identity in the post table as owner. Sounds easy right ?

#### Implementing with RBAC

Let’s look at that situation from a role based access control perspective. You can easily define specific roles or permissions to perform actions on posts, such as read, delete, edit etc. 

But what about the ownership? How to create a permission or role that defines users to be able to edit posts they created.

It’s clear that we can’t achieve this with a single role. 

A workaround solution would be assigning the **“owner”** role to the user when a post is created to differentiate it from other users. Plus, we need to add specific roles to each post to compare the user and owner roles. This is the point where roles and permissions don't fit well, as opposed to ReBAC. As we mentioned this can be easily achieved through ReBAC with a simple Database design.

#### ReBAC combined with RBAC

It’s important to notice that access control models can be used together in such scenarios. 

Although it's not reasonable to build ownership with roles and permissions. ReBAC ownership model works great with role based access control and it’s widely used. 

Let’s give an example of [deleting repository permission on Github](https://docs.github.com/en/repositories/creating-and-managing-repositories/deleting-a-repository). You can delete any repository or fork if you're either an organization owner or have admin permissions for the repository or fork.

![delete-repo](https://user-images.githubusercontent.com/34595361/213843097-2d18ea30-571b-4108-b4f0-c901aded7134.png)

For performing a delete action, GitHub uses both RBAC and ReBAC. This combination indicates that either you need to have an admin role or you need to be owner of the organization to delete a repository.

### Parent-Child & Hierarchies
Since being the owner of some resource can be also described as the parent of some resource, the parent-child model often be confused with ownership. Although they seem the same at first glance, they’re quite different.

Parent-child model is relevant with the nested relations of a child's resources. The general idea is granting parents access to perform actions on their children’s resources.

Think of a large business, in which departments have their own resources like files, documents, etc… 

We want users to view resources if only they’re a member of the department. So this prevents different users from achieving other departments' files. 

Notice that it’s not sufficient to say **'members can view department files'** — instead, we need to specify the parent of the user as the department.

![parent-child](https://user-images.githubusercontent.com/34595361/213843139-5be5d3aa-1afc-4c20-9e82-3ce0b0c46b8b.jpg)

What if we want to add RBAC in this scenario ?

#### ReBAC combined with RBAC

Let's say users who have admin or manager roles can view all of the files organization-wide.

Generally, this is a scenario we wouldn’t prefer in real life, since giving 'god mode' to a specific user role breaks the principle of [least privilege](https://delinea.com/what-is/least-privilege) and it's a nightmare at scale systems.

![parent-child Flowchart](https://user-images.githubusercontent.com/34595361/213843181-0cb4fa35-ba74-4248-9ba9-34dbcfcfe4df.jpg)

When combining roles and relationship-based access control be careful about the priority of enforcement - access checks. 

Most of the time you’ll need to check whether the user has admin or manager role first. If a user has it, then they can be authorized to perform the action. Unless the user doesn’t have one of these roles, then the system needs to check the parent child relation to decide.

#### Implementing with ABAC

Let's try to implement same scenario with using ABAC.

With ReBAC, access is granted based on the relationship between the user and the department. Let's say if a user is a member of the HR department, they automatically get access to HR files. 

This is straightforward – a user’s membership in a department directly determines their access rights.

To mimic this in ABAC, we would need to define attributes and create policies that consider these attributes.

More specifically, for each user, we would need attributes like **'Department=HR'**. Each file or document would also have attributes, like **'DepartmentAccess=HR'**.

Continuing, we would create policies like: ***"A user can access a file if the user's 'Department' attribute matches the file's 'DepartmentAccess' attribute."*** 

Sounds simple enough, right? But here's where it gets tricky.

As our organization grows and evolves, so do our departments. This means our ABAC system needs to keep up, constantly updating with new attributes for every new department, role, or type of document. 

Think about a user switching from the Marketing to the HR department – we'd need to change their access rights, and that's just one example. 

And if we have a document that needs to be shared across multiple departments? Well, that's another layer of complexity.

Also this increase the computational overhead. 

Every time someone requests access to a file, our system has to juggle and match all these attributes against our policies. 

In a large organization with tons of users and resources, this can really put a strain on our system. 

As a bottom line, a ReBAC system would handle these scenarios more naturally. A user's departmental membership would inherently define their access, without the need for constantly updating and evaluating a multitude of attributes and policies.

### User Groups & Teams

Grouping users helps to organize access control in a more structured way, especially at scale.

We examine the parent child relationship model with segmentation of resources (entities), we group resources (files) as in departments. 

Groups model more focused on segmentation of users or user sets rather than segmenting the resources. In particular, this model ensures that the user has a privilege to access to do some action on a resource based on its group, team etc.

Github repository access would be a great example for group specific privileges. 

Github enables you to [give a team access to a repository](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-team-access-to-an-organization-repository#giving-a-team-access-to-a-repository) or change a team's level of access to a repository in your repository settings.

![give-team-access](https://user-images.githubusercontent.com/34595361/213843202-d4be8cef-24b9-4aab-8e67-4ee7b1d1aed2.png)

Giving access to a team simply means members of that team can also access your private repository. 

The enforcement workflow is the same as other models. 

Most of the time you check whether the user has the relevant role or permissions, then you need to move on checking parent-child relation. Is the user still unauthorized ? if yes, then you need to check for each group the user belongs to.

## Summing Up 
We went through 3 common relationship based access control models  and tried to explain their structure with basic real world examples.

We contrast ReBAC with Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC), highlighting the challenges and inefficiencies of using RBAC or ABAC to replicate ReBAC's model, especially in large organizations

As I mentioned we're building an open source authorization service called [Permify](https://github.com/Permify/permify), designed and structured as a true ReBAC (Relationship-Based Access Control) solution. 

If you want to build ReBAC based robust authorization systems, we can help. Check out our [open source repository](https://github.com/Permify/permify/) or join our [Discord community](https://discord.com/invite/n6KfzYxhPp) to learn more!