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
How the evaluator uses tuples
During an access check, the evaluator runs in this order:
- Check role-based policies for a DENY. If any role policy explicitly denies
the action →
allowed: false. Stop. - Check role-based policies for an ALLOW. If any role policy grants the
action →
allowed: true. Stop. - Fall back to tuples. Only if
resourceIdis 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. - 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.
- The relation name equals the action name. If your tuple uses
relation: "editor", your access check must useaction: "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
| Scenario | Use |
|---|---|
| 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 permissions | ReBAC |