caduh

RBAC vs ABAC vs ReBAC

10 min read

A practical guide to choosing role-based, attribute-based, or relationship-based authorization for real products, with examples for SaaS apps, internal tools, B2B org models, and shared resources.

RBAC vs ABAC vs ReBAC

Choosing an authorization model that won't hurt later

Goal: help you pick the simplest authorization model that fits your product today without boxing yourself into rewrites when customers ask for teams, shared resources, delegated access, or context-aware rules.


TL;DR

  • Start with RBAC when permissions map cleanly to job functions like admin, editor, and viewer.
  • Reach for ABAC when decisions depend on attributes like department, region, data sensitivity, device trust, or time of day.
  • Reach for ReBAC when permissions depend on relationships like owner of document, member of workspace, viewer of parent folder, or manager of employee.
  • Most real systems end up hybrid: RBAC for broad defaults, ReBAC for shared resources and delegation, ABAC for context and guardrails.
  • If your product has Google Drive / GitHub / Notion / Slack-style sharing, ReBAC usually ages better than trying to fake everything with roles.
  • If your app is a classic internal admin portal with a small, stable permission matrix, plain RBAC is usually enough.

1) First: Authentication Is Not Authorization

Before the acronyms melt together:

  • Authentication answers: who is this user?
  • Authorization answers: can this user do this action on this resource right now?

This article is about the second question.

A useful mental model:

Can user U perform action A on resource R under context C?

Different models answer that question in different ways.


2) What Each Model Actually Means

2.1 RBAC: Role-Based Access Control

RBAC grants permissions through roles. Users are assigned roles, and roles carry permissions.

user -> role -> permissions

Examples:

  • admin can manage billing
  • editor can publish posts
  • support_agent can view tickets

This fits organizations well because roles usually line up with job functions.

2.2 ABAC: Attribute-Based Access Control

ABAC evaluates attributes about the subject, object, action, and environment.

allow if
  user.department == document.department
  AND user.clearance >= document.classification
  AND request.time < 18:00
  AND device.trusted == true

Examples:

  • HR staff can view records only in their region
  • finance approvals over $10,000 require a manager attribute
  • an API call is allowed only from a trusted network

2.3 ReBAC: Relationship-Based Access Control

ReBAC evaluates whether a user has the right relationship to a resource.

allow if
  user is owner of document
  OR user is editor of parent folder
  OR user is member of workspace that contains project

Examples:

  • Jane can view doc 123 because she is an editor on folder abc
  • Bob can manage repo foo because he is an admin of org acme
  • a contractor can access a project because they are assigned to that client account

3) The Fast Decision Rule

If you only remember one section, remember this:

Choose RBAC when

  • permissions are mostly static
  • users fall into a few clear buckets
  • resources do not have complicated sharing rules
  • you mainly need screen/menu/API access by role

Choose ABAC when

  • decisions depend on context or metadata
  • rules need to consider region, classification, device posture, shift, time window, or environment
  • you need central policy logic across many systems

Choose ReBAC when

  • your product has sharing, teams, ownership, delegation, or hierarchies
  • access should flow through containers like orgs, workspaces, folders, projects, or groups
  • customers ask for rules like “all project members can comment, but only workspace admins can export”

Use a hybrid when

  • you are building almost any B2B SaaS with collaborative data

That usually looks like:

  • RBAC for coarse roles like org_admin, billing_admin, member
  • ReBAC for per-resource access like project/repo/document sharing
  • ABAC for context checks like IP, device trust, data residency, or approval thresholds

4) The Real Trade-Offs

| Model | Best at | Gets painful when | Typical fit | |---|---|---|---| | RBAC | Simple, predictable permission matrices | resource-level sharing explodes role count | internal tools, admin panels, stable back-office apps | | ABAC | Flexible policies using metadata and context | attributes become messy, inconsistent, or hard to audit | regulated systems, enterprise policy layers, zero-trust style checks | | ReBAC | Fine-grained sharing and inheritance | graph modeling is new to the team, checks need careful design | collaborative SaaS, org/workspace/project/file products |

4.1 RBAC’s biggest risk: role explosion

RBAC starts clean:

  • admin
  • editor
  • viewer

Then real life arrives:

  • billing admin
  • project admin
  • project editor
  • external viewer
  • regional finance approver
  • read-only support with export disabled

If every exception becomes a new role, your model turns into a spreadsheet nobody trusts.

4.2 ABAC’s biggest risk: invisible complexity

ABAC looks elegant because you avoid endless roles. But if attributes come from five systems and half of them are stale or inconsistently named, the policy layer becomes hard to reason about.

Bad ABAC smells like:

  • nobody knows where an attribute is sourced
  • policies require reading three docs and two database tables
  • support cannot explain why a request was denied

4.3 ReBAC’s biggest risk: modeling discipline

ReBAC is powerful, but you need a clean object model.

You must define things like:

  • what object types exist?
  • what relations matter?
  • can permissions inherit from parent objects?
  • do explicit denies exist?
  • how deep can relationship expansion go?

If you skip that thinking, the graph becomes magical and hard to debug.


5) Concrete Examples

5.1 Internal admin portal → RBAC

You have:

  • support agents
  • managers
  • finance admins
  • super admins

Permissions are about screens and actions:

  • refund order
  • view customer notes
  • edit plan pricing
  • impersonate user

This is classic RBAC territory.

Minimal table shape:

CREATE TABLE roles (
  id BIGSERIAL PRIMARY KEY,
  name TEXT UNIQUE NOT NULL
);

CREATE TABLE permissions (
  id BIGSERIAL PRIMARY KEY,
  key TEXT UNIQUE NOT NULL
);

CREATE TABLE user_roles (
  user_id BIGINT NOT NULL,
  role_id BIGINT NOT NULL,
  PRIMARY KEY (user_id, role_id)
);

CREATE TABLE role_permissions (
  role_id BIGINT NOT NULL,
  permission_id BIGINT NOT NULL,
  PRIMARY KEY (role_id, permission_id)
);

Runtime check:

can(user, "ticket.refund")

5.2 Expense approvals by policy → ABAC

You want rules like:

  • users can approve expenses in their own department
  • amount must be under their approval limit
  • finance can override only during office hours
  • high-risk transactions need a trusted device

That is not a role problem. It is a policy problem.

Example policy shape:

allow:
  - action: expense.approve
    when:
      all:
        - user.department == expense.department
        - user.approval_limit >= expense.amount
        - request.device_trusted == true

5.3 Docs/workspaces/projects → ReBAC

You want rules like:

  • owners can manage a document
  • editors on a folder can edit files inside it
  • workspace admins can invite users
  • a project viewer gets read access to all tasks in that project

That is where ReBAC feels natural.

Example relationship tuples:

user:anne owner document:doc_1
user:bob editor folder:folder_a
folder:folder_a parent workspace:ws_7
user:maya admin workspace:ws_7
project:proj_9 parent workspace:ws_7
user:leo viewer project:proj_9

Example reasoning:

Can Bob edit document:doc_1?
Yes, if document:doc_1 is in folder:folder_a
and editors of folder:folder_a inherit edit on child docs.

6) Why B2B SaaS Usually Needs More Than RBAC

Many teams begin with org-level roles:

  • owner
  • admin
  • member

That works until customers ask for:

  • per-project access
  • guests
  • client portals
  • delegated admin
  • cross-org collaboration
  • “can view but not export”
  • “only managers in region X can approve”

If you force all of that into RBAC, you usually get one of two bad outcomes:

  • role explosion
  • permission checks scattered through app code

A better progression is:

Phase 1

RBAC only

  • org roles
  • basic permission matrix

Phase 2

RBAC + ReBAC

  • org roles for broad defaults
  • relationships for project/repo/doc/task access

Phase 3

RBAC + ReBAC + ABAC

  • add policy checks for context like region, classification, device trust, time window, amount thresholds, or legal constraints

7) What to Use for Common App Types

Web apps / internal dashboards

Default to RBAC first.

Use ABAC only if you truly have contextual rules. Add ReBAC only if users share resources with each other.

Collaborative SaaS

Default to RBAC + ReBAC.

Use org/workspace roles for broad admin powers and ReBAC for resource-level sharing.

Developer platforms / GitHub-style products

Default to ReBAC, often with RBAC layered on top.

Repos, orgs, teams, envs, projects, secrets, service accounts, and delegated access are relationship-heavy.

Regulated or policy-heavy enterprise systems

Default to ABAC + RBAC, and sometimes ReBAC too.

ABAC helps with environment and classification rules. RBAC still helps keep the coarse-grained model understandable.

APIs / microservices

For service authorization, keep it boring where possible:

  • RBAC/scopes for coarse API rights
  • ABAC for contextual checks like tenant, network, risk, or request claims
  • ReBAC only if the API serves collaborative resource graphs

8) A Practical Composition That Ages Well

Here is a model that works for many products:

Coarse-grained access: RBAC

Examples:

  • org_admin
  • billing_admin
  • member
  • support_readonly

Use RBAC for:

  • admin features
  • high-level product entitlements
  • navigation and API families

Fine-grained resource access: ReBAC

Examples:

  • user is owner of doc
  • team is editor on repo
  • project inherits access from workspace

Use ReBAC for:

  • sharing
  • inherited permissions
  • delegated access
  • guest access

Context guardrails: ABAC

Examples:

  • export allowed only from trusted devices
  • approval allowed only below threshold
  • data visible only in same residency zone

Use ABAC for:

  • risk controls
  • policy constraints
  • environment conditions
  • compliance-driven checks

In code, the flow often looks like:

if (!hasRole(user, "member")) return deny();
if (!canAccessResource(user, "view", document)) return deny();
if (!passesPolicy(user, "document.export", document, context)) return deny();
return allow();

That is not “impure.” It is usually the most maintainable setup.


9) Migration Advice: Don’t Rewrite All at Once

If you already have RBAC and it is starting to creak, do not throw it away immediately.

Step 1: keep RBAC for the coarse layer

Leave existing org/admin/support roles alone.

Step 2: identify relationship-heavy resources

Usually:

  • documents
  • folders
  • projects
  • repos
  • dashboards
  • client accounts

Step 3: move per-resource access out of app conditionals

Instead of checks like:

if (user.role === "admin" || doc.ownerId === user.id || teamIds.includes(doc.teamId))

move toward a model where the relationships are stored explicitly.

Step 4: add ABAC last, only for genuine policy needs

ABAC is powerful, but it should usually be the final layer, not the first thing you build.


10) Sharp Edges Every Team Hits

10.1 Confusing scopes/claims with authorization truth

JWT claims can help, but they should not become your only source of truth for fine-grained access if permissions change frequently.

10.2 Embedding every permission in the token

This causes stale permissions, oversized tokens, and messy revocation.

10.3 Mixing product roles and org chart roles carelessly

“Manager” in HR and “manager” in app permissions are often not the same thing.

10.4 No audit trail for why access was granted

Support and security teams eventually ask:

  • why was this user allowed?
  • through which role, attribute, or relationship?

If your system cannot answer that, incidents get slow and expensive.

10.5 Deny rules with unclear precedence

Once you add exceptions, define precedence early:

  • explicit deny beats allow?
  • direct relationship beats inherited deny?
  • system admin bypasses everything?

Write it down. Test it.

10.6 Tenant boundaries leaking through shared roles

In multi-tenant systems, roles must usually be scoped to a tenant/org/workspace, not global.

Bad:

user:123 has role admin

Better:

user:123 has role admin in org:acme

11) A Simple Modeling Checklist

Before choosing a model, answer these questions:

  1. What are the resources?
  2. What are the actions on each resource?
  3. Are permissions mostly about job function, context, or resource relationship?
  4. Does access inherit from parents like org -> workspace -> project -> doc?
  5. Do customers need sharing, guests, or delegation?
  6. Do policies depend on time, network, device, region, or classification?
  7. Can support explain a deny in one sentence?
  8. Can you audit the answer later?

Your answers usually reveal the model choice quickly.


12) The 2 AM Runbook

When prod says “users are seeing random permission bugs,” check these first:

  1. Scope the blast radius
    • one tenant, one resource type, or everyone?
  2. Check the source of truth
    • role assignment table, attribute service, relationship tuples/graph
  3. Check caching
    • stale auth cache and stale JWT claims cause a lot of ghost bugs
  4. Check inheritance rules
    • parent-child propagation often breaks after refactors
  5. Check tenant scoping
    • especially with background jobs and admin tooling
  6. Explain one concrete decision end-to-end
    • “Why can Jane edit document X right now?”
  7. Add decision logging
    • include role, relationship, attribute, and policy inputs

If your team cannot explain one concrete allow/deny decision clearly, the model is too implicit.


13) Recommended Defaults

If you are starting something new:

Choose RBAC if

  • the app is mostly internal
  • permissions are screen/action based
  • resource-level sharing is rare

Choose RBAC + ReBAC if

  • it is collaborative B2B SaaS
  • customers organize data into orgs/workspaces/projects/folders
  • you know sharing is coming

Add ABAC if

  • you need context-aware policy
  • you have compliance or risk conditions
  • decisions depend on metadata beyond role and ownership

The winning move is usually not picking the fanciest model. It is picking the model your team can reason about, audit, and evolve.


FAQ

Is ReBAC just a more complicated RBAC?

Not really. RBAC answers “what can this role do?” ReBAC answers “what is this user’s relationship to this resource?” They solve different kinds of complexity.

Can ABAC replace RBAC?

Sometimes, but that does not mean it should. RBAC is still easier for humans to understand and administer for broad permissions.

Can ReBAC replace RBAC?

In some systems, yes. In practice, many teams still keep coarse roles because they are simple and useful.

Is Google Drive style sharing basically ReBAC?

Yes. Ownership, folder inheritance, workspace membership, and delegated access are classic relationship-based patterns.

Should I put all authorization in JWT claims?

Usually no. Coarse entitlements maybe. Fast-changing or resource-level permissions usually need fresher checks.

What should small teams start with?

Start with RBAC unless your product is obviously relationship-heavy from day one.


Final Take

  • RBAC is the best default for simple, stable permission matrices.
  • ABAC is best for context-aware policy decisions.
  • ReBAC is best for collaborative products with sharing and inheritance.
  • The most durable production model is often RBAC for defaults, ReBAC for resources, ABAC for guardrails.

Pick the model that matches the shape of your product, not the one with the coolest acronym.