Search by

ptondereau / biscuit-laravel

rooferz

Laravel integration for Biscuit authorization tokens

Package info

github.com/ptondereau/biscuit-laravel

pkg:composer/ptondereau/biscuit-laravel

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

dev-main / 0.6.x-dev 2026-10-10 20:27 UTC

This package is auto-updated.

Last update: 2026-10-10 20:27:31 UTC


README

Laravel integration for Biscuit authorization tokens.

This repository is a read-only mirror. The package is maintained in the packages/laravel/ directory of ptondereau/biscuit-php and synced here automatically. Please open issues and pull requests against the main repository.

Requirements

  • PHP 8.2 or later
  • Laravel 12 or 13
  • The biscuit_php extension: pie install ptondereau/biscuit-php

Installation

composer require ptondereau/biscuit-laravel
php artisan vendor:publish --tag=biscuit-config

Set the root key in .env, as a hex string or a PEM file:

BISCUIT_PUBLIC_KEY=ed25519/...
# BISCUIT_PUBLIC_KEY_FILE=/path/to/public.pem

The private key (BISCUIT_PRIVATE_KEY or BISCUIT_PRIVATE_KEY_FILE) is only needed to mint tokens.

Authorization

A Biscuit is not an authentication token. Keep your guards (session, Sanctum, Passport) for users. The token only carries rights.

The token comes from the Authorization: Bearer header, or from the cookie named in BISCUIT_COOKIE. Its signature is checked against the public key.

Declare Datalog policies in config/biscuit.php:

'policies' => [
    'posts.read' => 'allow if right("posts", "read")',
    'posts.edit' => 'allow if right({resource}, "edit")',
],

Each policy is a Gate ability. It works with can middleware, Gate::allows(), @can and $this->authorize():

Route::middleware(['auth', 'can:posts.edit,post'])->put('/posts/{post}', UpdatePost::class);

The Gate argument fills the policy placeholders:

Argument Parameters
Eloquent model {resource} = primary key
string or int {resource} = the value
associative array each key is a placeholder

Placeholders the policy does not use are ignored. Values must be strings, integers or booleans. The authorizer adds the current time, so checks such as check if time($t), $t < 2030-01-01T00:00:00Z expire tokens.

An ability that starts with allow or deny is used as an inline policy: Gate::allows('allow if right("posts", "read")').

A Biscuit policy is denied when the request has no valid token, whoever the user is. Other abilities go to the app's own gates and policies.

Minting tokens

use Biscuit\Auth\BiscuitBuilder;
use Biscuit\Auth\PrivateKey;

$token = (new BiscuitBuilder('user({id}); right("posts", "read");', ['id' => 'alice']))
    ->build(app(PrivateKey::class))
    ->toBase64();

License

Apache-2.0