Skip to main content

Zanzibar Relationship Checks

Zanzibar (from Google's 2019 paper of the same name) models authorization as a graph of relation tuples. Each tuple has the form object#relation@subject — for example document:readme#editor@user:alice reads as "alice is an editor of document readme". A check then asks "does a path exist in the relation graph from this subject to this object under this relation, given the schema's rewrites?"

Use Zanzibar when access is driven by hierarchy and relationships: folders containing files, teams owning projects, organizations containing workspaces. Permission inheritance (folder editors can edit the folder's files) and shared access (all members of a team can view a document) are natural in this model and awkward in RBAC.

POST /api/v1/zanzibar/check

How Zanzibar Checks Work

RBAC asks "does this user have permission X?" — a flat yes/no against a role set. Zanzibar asks "is this user related to this object through this relation?" — and the engine walks the graph to decide.

During a check, LumoAuth:

  1. Looks up direct tuples that match object#relation@subject.
  2. Follows userset rewrites in the schema: for example, if editor implies viewer, an editor tuple also satisfies a viewer check.
  3. Follows computed usersets across relations: for example, viewers of a parent folder become viewers of its documents.
  4. Returns allowed: true if any path is found, otherwise false.

A companion expand operation can return the full tree of subjects that satisfy a given object#relation, which is useful for audit and UI rendering.

Request Format

FieldTypeRequiredDescription
objectstringYesResource being accessed (namespace:id)
relationstringYesType of access (e.g., viewer, editor, owner)
userstringYesSubject (namespace:id or namespace:id#relation userset)

Basic Example

curl -X POST https://api.example.com/api/v1/zanzibar/check \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"object": "document:annual-report",
"relation": "editor",
"user": "user:alice"
}'
{
"allowed": true,
"object": "document:annual-report",
"relation": "editor",
"user": "user:alice"
}

Understanding the Format

Objects

Objects are the resources in your system, named namespace:id.

ExampleMeaning
document:readmeA document with ID "readme"
folder:projectsA folder named "projects"
organization:acmeOrganization "acme"
repository:myappA repository named "myapp"

Relations

A relation is the kind of edge between an object and a subject. Relation names are defined per namespace in the schema.

RelationTypical UseUsually Implies
ownerFull control over a resourceeditor, viewer
editorCan modify a resourceviewer
viewerRead-only access-
memberBelongs to a group or orgviewer (of group resources)
adminAdministrative accessowner, member
parentHierarchical containmentPermission inheritance

Subjects

A subject is either a concrete identity or a userset — a reference to every entity holding a given relation on another object.

FormatExampleMeaning
namespace:iduser:aliceA specific user
namespace:id#relationteam:engineering#memberAll members of the engineering team
namespace:id#relationorganization:acme#adminAll admins of the Acme org

Userset Subjects

Userset subjects let you attach an entire group to an object in a single tuple. The check walks into the userset when evaluating.

Given tuples like team:engineering#member@user:bob and document:api-docs#viewer@team:engineering#member, the following check returns allowed: true:

curl -X POST https://api.example.com/api/v1/zanzibar/check \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"object": "document:api-docs",
"relation": "viewer",
"user": "user:bob"
}'

The engine reasons:

  1. Bob is a member of team:engineering.
  2. team:engineering#member is a viewer of document:api-docs.
  3. Therefore Bob is a viewer of document:api-docs.

Examples

Document Sharing (Google Docs Style)

# Can Carol view the Q4 report?
curl -X POST https://api.example.com/api/v1/zanzibar/check \
-d '{"object": "document:q4-report", "relation": "viewer", "user": "user:carol"}'
# Result: allowed: true (Carol is on finance team, which has viewer access)

# Can Carol edit the Q4 report?
curl -X POST https://api.example.com/api/v1/zanzibar/check \
-d '{"object": "document:q4-report", "relation": "editor", "user": "user:carol"}'
# Result: allowed: false (Carol only has view access via team membership)

Folder Hierarchy

# Can Alice view the readme?
curl -X POST https://api.example.com/api/v1/zanzibar/check \
-d '{"object": "document:readme", "relation": "viewer", "user": "user:alice"}'
# Result: allowed: true (Alice owns the parent folder)

GitHub-Style Repository Access

# Org structure
organization:acme#admin@user:ceo
organization:acme#member@user:developer

# Team in org
team:platform#parent@organization:acme
team:platform#member@user:developer

# Repo owned by team
repository:api-service#owner@team:platform#member

# Schema: org admins are admins of all repos
# Schema: team members who own a repo are maintainers

Comparison: Zanzibar vs RBAC

AspectRBAC CheckZanzibar Check
QuestionDoes user have permission?Does user have relation to object?
Exampledocument.editdocument:123#editor@user:456
Resource awareNo (global permission)Yes (specific resource)
InheritanceRole hierarchy onlyObject + relation hierarchy
Best forAdmin features, global actionsShared resources, hierarchies