mvonline/openfga-laravel-rbac

PHP and Laravel SDK for using OpenFGA as an RBAC authorization operator.

Maintainers

Package info

github.com/mvonline/openfga-laravel-rbac

pkg:composer/mvonline/openfga-laravel-rbac

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.1 2026-07-14 12:44 UTC

This package is auto-updated.

Last update: 2026-07-14 12:46:51 UTC


README

PHP Laravel License

PHP and Laravel SDK for using OpenFGA as an RBAC and authorization service.

This package provides:

  • A framework-agnostic PHP OpenFGA HTTP client
  • Laravel auto-discovery, facades, config publishing, Gate integration, and middleware
  • RBAC helper methods for roles, permissions, assignments, and common checks
  • Advanced OpenFGA API support for contextual tuples, batch checks, list users, changes, assertions, stores, and authorization models
  • Docker-friendly test workflow, so PHP does not need to be installed on the host machine

Requirements

  • PHP ^8.1
  • Composer
  • OpenFGA server or OpenFGA-compatible endpoint
  • Laravel 10, 11, or 12 for Laravel-specific features

Installation

composer require mvonline/openfga-laravel-rbac

Laravel Setup

Publish the configuration file:

php artisan vendor:publish --tag=openfga-rbac-config

Configure your OpenFGA connection:

OPENFGA_API_URL=http://localhost:8080
OPENFGA_STORE_ID=01H...
OPENFGA_AUTHORIZATION_MODEL_ID=01H...
OPENFGA_TOKEN=

The package auto-registers these aliases in Laravel:

  • OpenFga for the low-level OpenFGA client
  • OpenFgaRbac for RBAC helper methods

OpenFGA Model Example

This model supports users, roles, a registry for listing roles and permissions, and a tenant resource.

model
  schema 1.1

type user

type permission

type rbac
  relations
    define role: [role]
    define permission: [permission]

type role
  relations
    define assignee: [user]

type tenant
  relations
    define admin: [user, role#assignee]
    define member: [user, role#assignee] or admin

For resource-specific permissions, add relations to your resource types. Example:

type invoice
  relations
    define viewer: [user, role#assignee]
    define editor: [user, role#assignee]
    define owner: [user]

Laravel Usage

Low-Level Checks

use OpenFga;

$allowed = OpenFga::check(
    'user:' . $user->id,
    'viewer',
    'invoice:' . $invoice->id,
);

RBAC Helpers

use OpenFgaRbac;

OpenFgaRbac::createRole('billing-admin');
OpenFgaRbac::createPermission('invoice.view');
OpenFgaRbac::assignRole($user->id, 'billing-admin');
OpenFgaRbac::grantRolePermission('billing-admin', 'viewer', 'invoice', $invoice->id);

if (OpenFgaRbac::can($user->id, 'viewer', 'invoice', $invoice->id)) {
    // authorized
}

Role And Permission Queries

$roles = OpenFgaRbac::listRoles();
$permissions = OpenFgaRbac::listPermissions();
$userRoles = OpenFgaRbac::userRoles($user->id);
$roleUsers = OpenFgaRbac::usersAssignedToRole('billing-admin');
$rolePermissions = OpenFgaRbac::rolePermissions('billing-admin');

Any Or All Permission Checks

$canReadOrEdit = OpenFgaRbac::canAny($user->id, ['viewer', 'editor'], 'invoice', $invoice->id);
$canReadAndEdit = OpenFgaRbac::canAll($user->id, ['viewer', 'editor'], 'invoice', $invoice->id);

Laravel Middleware

Single check:

Route::get('/invoices/{invoice}', InvoiceController::class)
    ->middleware('openfga:viewer,invoice:{invoice}');

Any check can pass:

Route::get('/invoices/{invoice}', InvoiceController::class)
    ->middleware('openfga.any:owner:invoice:{invoice},admin:tenant:acme');

Every check must pass:

Route::patch('/invoices/{invoice}', InvoiceController::class)
    ->middleware('openfga.all:viewer:invoice:{invoice},member:tenant:acme');

Route placeholders such as {invoice} are resolved from Laravel route parameters. If the parameter is an Eloquent model, the middleware uses getKey().

Plain PHP Usage

use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Psr7\HttpFactory;
use OpenFgaRbac\Client;
use OpenFgaRbac\Config;

$http = new GuzzleClient();
$factory = new HttpFactory();

$openfga = new Client(
    new Config(
        apiUrl: 'http://localhost:8080',
        storeId: '01H...',
        authorizationModelId: '01H...',
        token: null,
    ),
    $http,
    $factory,
    $factory,
);

$allowed = $openfga->check('user:123', 'viewer', 'invoice:2026-001');

Advanced OpenFGA Client

Contextual Tuples And Conditions

use OpenFgaRbac\TupleKey;

$result = $openfga->checkRaw(
    user: 'user:123',
    relation: 'viewer',
    object: 'document:roadmap',
    contextualTuples: [
        TupleKey::make('user:123', 'member', 'team:finance'),
    ],
    context: [
        'ip' => '127.0.0.1',
    ],
    consistency: 'HIGHER_CONSISTENCY',
);

Batch Checks

$batch = $openfga->batchCheck([
    [
        'correlation_id' => 'invoice-view',
        'tuple_key' => [
            'user' => 'user:123',
            'relation' => 'viewer',
            'object' => 'invoice:2026-001',
        ],
    ],
]);

List Objects And Users

$objects = $openfga->listObjects('user:123', 'viewer', 'invoice');

$users = $openfga->listUsers(
    object: 'invoice:2026-001',
    relation: 'viewer',
    userFilters: [
        ['type' => 'user'],
    ],
);

Tuple Writes

use OpenFgaRbac\TupleKey;

$openfga->writeTuple('user:123', 'viewer', 'invoice:2026-001');
$openfga->deleteTuple('user:123', 'viewer', 'invoice:2026-001');

$openfga->writeAdvanced(
    writes: [
        TupleKey::make('user:123', 'viewer', 'invoice:2026-001'),
    ],
    deletes: [
        TupleKey::make('user:456', 'viewer', 'invoice:2026-001'),
    ],
    onDuplicate: 'ignore',
    onMissing: 'ignore',
);

Models, Assertions, Changes, And Stores

$models = $openfga->readAuthorizationModels();
$model = $openfga->readAuthorizationModel('01H...');

$authorizationModelId = $openfga->writeAuthorizationModel([
    'schema_version' => '1.1',
    'type_definitions' => [
        ['type' => 'user'],
    ],
]);

$openfga->writeAssertions('01H...', [
    [
        'tuple_key' => [
            'user' => 'user:123',
            'relation' => 'viewer',
            'object' => 'invoice:2026-001',
        ],
        'expectation' => true,
    ],
]);

$assertions = $openfga->readAssertions('01H...');
$changes = $openfga->readChanges(type: 'invoice');
$stores = $openfga->listStores();
$store = $openfga->getStore();

Available Client Methods

Low-level OpenFGA client:

  • check
  • checkRaw
  • batchCheck
  • listObjects
  • listObjectsRaw
  • listUsers
  • expand
  • readTuples
  • writeTuple
  • deleteTuple
  • write
  • delete
  • writeAdvanced
  • writeAuthorizationModel
  • readAuthorizationModel
  • readAuthorizationModels
  • writeAssertions
  • readAssertions
  • readChanges
  • createStore
  • listStores
  • getStore
  • deleteStore

RBAC helper methods:

  • createRole
  • deleteRole
  • createPermission
  • deletePermission
  • listRoles
  • getAllRoles
  • listPermissions
  • getAllPermissions
  • assignRole
  • revokeRole
  • hasRole
  • userRoles
  • rolesAssignedToUser
  • usersAssignedToRole
  • grantRolePermission
  • revokeRolePermission
  • rolePermissions
  • can
  • canAny
  • canAll

Testing

Run tests in Docker:

docker run --rm -v "$PWD:/app" -w /app composer:2 bash -lc "composer install && vendor/bin/phpunit"

Or use Composer:

composer test

Versioning

This package follows semantic versioning. Tag releases with Git tags:

git tag v0.1.0
git push origin v0.1.0

Packagist will expose tagged versions as Composer releases.

License

MIT