Skip to main content

Relationships

RBAC answers "who can do what across the organization." ReBAC answers "who is related to this specific thing."

The problem RBAC can't solve​

Roles work well when permissions are global — every Editor has the same access everywhere. But real applications have per-resource access:

  • Alice can edit this document but not that one
  • Bob is a member of this project but not that one
  • The marketing team can access this folder but not finance

You could create a separate role for every resource. That quickly becomes thousands of roles. ReBAC solves this with a different mental model.

How relationships work​

Instead of assigning roles to people and permissions to roles, you define direct relationships between a subject and an object:

Each relationship is a (subject, relation, object) tuple. The relation name IS the action in your access check. No translation layer, no permission mapping. If Alice has the read relation to document:123, then action: "read" on resource: "document", resourceId: "123" returns allowed: true.

End-to-end example​

Step 1 — Write a tuple. Grant Alice the read relation to document 123:

curl -X POST https://api.wardenauthz.com/v1/scope/workspace-eng/tuples \
-H "x-api-key: YOUR_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"writes": [
{ "subject": "user:alice", "relation": "read", "object": "document:123" }
],
"deletes": []
}'

Step 2 — Check access. Ask: can Alice read document 123?

curl -X POST https://api.wardenauthz.com/v1/access/check \
-H "x-api-key: YOUR_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"subjectId": "user:alice",
"resource": "document",
"resourceId": "123",
"action": "read",
"scopeId": "workspace-eng"
}'
{ "allowed": true }

Alice has a read relationship to document:123, so action: "read" on resource: "document", resourceId: "123" matches. The tuple grants access.

Step 3 — Check a different action. Can Alice write document 123?

curl -X POST https://api.wardenauthz.com/v1/access/check \
-H "x-api-key: YOUR_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"subjectId": "user:alice",
"resource": "document",
"resourceId": "123",
"action": "write",
"scopeId": "workspace-eng"
}'
{ "allowed": false }

Alice only has read — no write relation exists for her on this document.

Writing tuples​

Writes and deletes in one call. Up to 100 operations per request. Writes are idempotent — writing the same tuple twice has no duplicate effect.

curl -X POST https://api.wardenauthz.com/v1/scope/workspace-eng/tuples \
-H "x-api-key: YOUR_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"writes": [
{ "subject": "user:alice", "relation": "read", "object": "document:123" },
{ "subject": "user:bob", "relation": "write", "object": "document:123" }
],
"deletes": [
{ "subject": "user:charlie", "relation": "read", "object": "document:123" }
]
}'

Querying​

# Everything Alice is related to
GET /v1/scope/workspace-eng/tuples?subjectId=user:alice

# Everyone related to document 123
GET /v1/scope/workspace-eng/tuples-by-resource?resourceType=document&resourceId=123

Full API reference

How the evaluator uses tuples​

During an access check, the evaluator runs in this order:

  1. Check role-based policies for a DENY. If any role policy explicitly denies the action → allowed: false. Stop.
  2. Check role-based policies for an ALLOW. If any role policy grants the action → allowed: true. Stop.
  3. Fall back to tuples. Only if resourceId is set in the check. The evaluator looks up whether a tuple exists matching the exact (subjectId, relation=action, resourceType=resource, resourceId) combination. If it does → allowed: true.
  4. Default deny. Nothing matched → allowed: false.

Tuples are a fallback, not a replacement. You can mix RBAC and ReBAC — role policies handle global permissions, tuples handle per-resource exceptions.

important
  • The relation name equals the action name. If your tuple uses relation: "editor", your access check must use action: "editor".
  • Tuples require resourceId. Without a specific resource instance, the tuple check is skipped entirely.
  • Deny policies take priority. A role-based deny prevents the tuple from being consulted.

When to use ReBAC vs RBAC​

ScenarioUse
Fixed roles across an org (Viewer, Editor, Admin)RBAC
Per-resource sharing (Google Docs)ReBAC
Hierarchical access (folders → files)ReBAC
Large number of objects with per-object permissionsReBAC