sseffa / zanzibar-php
Google Zanzibar-style authorization system for PHP
dev-main
2026-02-08 12:15 UTC
Requires
- php: ^8.2
- psr/simple-cache: ^3.0
Requires (Dev)
- phpunit/phpunit: ^10.0
- symfony/cache: ^6.0|^7.0
This package is auto-updated.
Last update: 2026-02-08 12:15:28 UTC
README
Google Zanzibar-style authorization for PHP. Works with Laravel and Symfony.
Install
composer require sseffa/zanzibar-php
Quick Start
use Zanzibar\Zanzibar; use Zanzibar\Config\NamespaceConfig; $zanzibar = Zanzibar::create() ->withNamespace( NamespaceConfig::create('document') ->addRelation('owner') ->addRelationIncluding('editor', 'owner') ->addRelationIncluding('viewer', 'editor') ) ->build(); // Grant permission $zanzibar->allow('document:123', 'viewer', 'user:alice'); // Check permission $zanzibar->can('document:123', 'viewer', 'user:alice'); // true // Owner inherits editor and viewer $zanzibar->allow('document:123', 'owner', 'user:bob'); $zanzibar->can('document:123', 'viewer', 'user:bob'); // true
Features
- Tuple-based model:
(object, relation, subject) - Relation inheritance: owner -> editor -> viewer
- Group permissions:
group:team#member - Wildcards:
user:*for public access - Exclusion: subscriber AND NOT banned
- Folder hierarchy: inherit permissions from parent
Laravel
Auto-discovered. Publish config:
php artisan vendor:publish --tag=zanzibar-config
// config/zanzibar.php 'namespaces' => [ 'document' => [ 'owner' => null, 'editor' => 'owner', 'viewer' => 'editor', ], ],
Usage:
use Zanzibar\Laravel\Facades\Zanzibar; Zanzibar::allow('document:1', 'viewer', 'user:1'); Zanzibar::can('document:1', 'viewer', 'user:1');
Symfony
Register bundle:
// config/bundles.php Zanzibar\Symfony\ZanzibarBundle::class => ['all' => true],
# config/packages/zanzibar.yaml zanzibar: secret: '%env(APP_SECRET)%' namespaces: document: owner: ~ editor: owner viewer: editor
Advanced
Group-based access
use Zanzibar\Core\SubjectRef; $zanzibar->allow('group:team', 'member', 'user:alice'); $zanzibar->allow('document:1', 'viewer', SubjectRef::userset('group', 'team', 'member')); $zanzibar->can('document:1', 'viewer', 'user:alice'); // true
Wildcard (public)
$zanzibar->allow('video:1', 'viewer', SubjectRef::wildcard('user')); $zanzibar->can('video:1', 'viewer', 'user:anyone'); // true
Exclusion (banned users)
use Zanzibar\Config\Rewrite\{ComputedUserset, ExclusionUserset}; NamespaceConfig::create('channel') ->addRelation('subscriber') ->addRelation('banned') ->addRelationWithRewrite('can_view', new ExclusionUserset( base: new ComputedUserset('subscriber'), subtract: new ComputedUserset('banned'), ));
Folder hierarchy
use Zanzibar\Config\Rewrite\{DirectUserset, ComputedUserset, TupleToUserset, UnionUserset}; NamespaceConfig::create('folder') ->addRelation('parent') ->addRelationWithRewrite('viewer', new UnionUserset([ new DirectUserset(), new TupleToUserset('parent', 'viewer'), ])); $zanzibar->allow('folder:root', 'viewer', 'user:alice'); $zanzibar->allow('folder:child', 'parent', 'folder:root'); $zanzibar->can('folder:child', 'viewer', 'user:alice'); // true
Test
composer test
License
MIT