DEV Community

Alex Spinov
Alex Spinov

Posted on

SpiceDB Has a Free API: Google Zanzibar-Inspired Authorization System

SpiceDB is an open-source authorization system inspired by Google's Zanzibar paper. It provides fine-grained, relationship-based access control (ReBAC) with a type-safe schema language and millisecond permission checks.

What Is SpiceDB?

SpiceDB by AuthZed implements the Zanzibar authorization model used internally at Google for services like Drive, Calendar, and Cloud. It stores relationships between objects and checks permissions in real-time.

Key Features:

  • Zanzibar-inspired architecture
  • Relationship-based access control (ReBAC)
  • Type-safe schema language
  • Millisecond permission checks
  • gRPC and HTTP API
  • Watch API for real-time updates
  • Multiple storage backends
  • Consistency guarantees (ZedTokens)

Quick Start

# Docker
docker run -d --name spicedb -p 50051:50051 -p 8443:8443 \
  authzed/spicedb serve --grpc-preshared-key "somerandomkeyhere"

# Install CLI
brew install authzed/tap/zed

# Set context
zed context set local localhost:50051 somerandomkeyhere --insecure
Enter fullscreen mode Exit fullscreen mode

Define Schema

// Schema definition
definition user {}

definition organization {
    relation admin: user
    relation member: user
    permission can_manage = admin
    permission can_view = admin + member
}

definition document {
    relation owner: user
    relation editor: user | organization#member
    relation viewer: user | organization#member
    relation org: organization
    permission can_edit = owner + editor + org->can_manage
    permission can_view = can_edit + viewer + org->can_view
    permission can_delete = owner
}
Enter fullscreen mode Exit fullscreen mode

SpiceDB API: Write Relationships and Check Permissions

from authzed.api.v1 import (
    Client, WriteRelationshipsRequest, RelationshipUpdate,
    CheckPermissionRequest, ObjectReference, SubjectReference,
    Relationship
)
import grpc

# Connect
channel = grpc.insecure_channel("localhost:50051")
client = Client(channel, credentials=grpc.metadata_call_credentials(
    lambda context, callback: callback([("authorization", "Bearer somerandomkeyhere")], None)
))

# Write relationships
client.WriteRelationships(WriteRelationshipsRequest(
    updates=[
        RelationshipUpdate(
            operation=RelationshipUpdate.OPERATION_TOUCH,
            relationship=Relationship(
                resource=ObjectReference(object_type="document", object_id="doc-1"),
                relation="owner",
                subject=SubjectReference(object=ObjectReference(object_type="user", object_id="alice"))
            )
        ),
        RelationshipUpdate(
            operation=RelationshipUpdate.OPERATION_TOUCH,
            relationship=Relationship(
                resource=ObjectReference(object_type="document", object_id="doc-1"),
                relation="viewer",
                subject=SubjectReference(object=ObjectReference(object_type="user", object_id="bob"))
            )
        )
    ]
))

# Check permission
result = client.CheckPermission(CheckPermissionRequest(
    resource=ObjectReference(object_type="document", object_id="doc-1"),
    permission="can_edit",
    subject=SubjectReference(object=ObjectReference(object_type="user", object_id="alice"))
))
print(f"Alice can edit: {result.permissionship == 2}")  # PERMISSIONSHIP_HAS_PERMISSION

result = client.CheckPermission(CheckPermissionRequest(
    resource=ObjectReference(object_type="document", object_id="doc-1"),
    permission="can_edit",
    subject=SubjectReference(object=ObjectReference(object_type="user", object_id="bob"))
))
print(f"Bob can edit: {result.permissionship == 2}")  # False, bob is viewer only
Enter fullscreen mode Exit fullscreen mode

HTTP API

# Check permission via HTTP
curl -X POST http://localhost:8443/v1/permissions/check \
  -H 'Authorization: Bearer somerandomkeyhere' \
  -H 'Content-Type: application/json' \
  -d '{"resource":{"objectType":"document","objectId":"doc-1"},"permission":"can_view","subject":{"object":{"objectType":"user","objectId":"bob"}}}'

# Write relationship via HTTP
curl -X POST http://localhost:8443/v1/relationships/write \
  -H 'Authorization: Bearer somerandomkeyhere' \
  -H 'Content-Type: application/json' \
  -d '{"updates":[{"operation":"OPERATION_TOUCH","relationship":{"resource":{"objectType":"document","objectId":"doc-2"},"relation":"editor","subject":{"object":{"objectType":"user","objectId":"charlie"}}}}]}'
Enter fullscreen mode Exit fullscreen mode

Resources


Need to scrape web data for your authorization system? Check out my web scraping tools on Apify — production-ready actors for Reddit, Google Maps, and more. Questions? Email me at spinov001@gmail.com

Top comments (0)