Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PHP

PHP bindings for Biscuit are available on GitHub and on Packagist. They wrap the Biscuit Rust library through a native PHP extension built with ext-php-rs.

Warning: This library is currently in beta. The API may change in future releases.

Requirements: PHP >= 8.1

All classes live under the Biscuit\Auth namespace.

Install

Prebuilt binaries are available on the GitHub releases page. You can also compile the extension from source — see the project README for build instructions.

In composer.json:

{
    "require": {
        "ext-biscuit-php": "*"
    }
}

Create a root key

use Biscuit\Auth\KeyPair;
use Biscuit\Auth\Algorithm;

// Ed25519 (default)
$root = new KeyPair();

// or explicitly choose an algorithm
$root = new KeyPair(Algorithm::Secp256r1);

Keys can also be loaded from existing material:

use Biscuit\Auth\PrivateKey;
use Biscuit\Auth\PublicKey;

$privateKey = new PrivateKey("<hex string>");
$privateKey = PrivateKey::fromPem($pem);

$publicKey = new PublicKey("<hex string>");
$publicKey = PublicKey::fromPem($pem);

Create a token

use Biscuit\Auth\BiscuitBuilder;

$userId = "1234";
$builder = new BiscuitBuilder('user({id})', ['id' => $userId]);
$builder->addCode('check if resource("file1")');
$builder->addCode('right({right})', ['right' => 'read']);

$token = $builder->build($root->getPrivateKey());
echo $token->toBase64();

Facts, rules and checks can also be added through dedicated types:

use Biscuit\Auth\Fact;
use Biscuit\Auth\Rule;
use Biscuit\Auth\Check;

$builder = new BiscuitBuilder();
$builder->addFact(new Fact('user({id})', ['id' => $userId]));
$builder->addRule(new Rule('can_access($u) <- user($u)'));
$builder->addCheck(new Check('check if user($u)'));

$token = $builder->build($root->getPrivateKey());

Authorize a token

use Biscuit\Auth\Biscuit;
use Biscuit\Auth\AuthorizerBuilder;
use Biscuit\Auth\Policy;

$publicKey = $root->getPublicKey();
$token = Biscuit::fromBase64("<base64 string>", $publicKey);

$authBuilder = new AuthorizerBuilder();
$authBuilder->addCode('resource("file1")');
$authBuilder->addCode('operation("read")');
$authBuilder->addPolicy(new Policy('allow if user({id}), right("read")', ['id' => '1234']));
$authBuilder->setTime(); // adds the current timestamp

$authorizer = $authBuilder->build($token);

// returns the index of the matched policy (0 here),
// throws AuthorizerError if denied
$acceptedPolicy = $authorizer->authorize();

Attenuate a token

use Biscuit\Auth\BlockBuilder;

$token = Biscuit::fromBase64("<base64 string>", $publicKey);

// restrict to read only
$block = new BlockBuilder();
$block->addCode('check if operation("read")');
$attenuatedToken = $token->append($block);
echo $attenuatedToken->toBase64();

Third-party blocks

use Biscuit\Auth\KeyPair;
use Biscuit\Auth\BlockBuilder;

$thirdPartyKp = new KeyPair();

// the token holder creates a request
$request = $token->thirdPartyRequest();

// the third party creates and signs a block
$externalBlock = new BlockBuilder();
$externalBlock->addCode('external_fact("verified")');
$signedBlock = $request->createBlock($thirdPartyKp->getPrivateKey(), $externalBlock);

// the token holder appends the signed block
$attested = $token->appendThirdParty($thirdPartyKp->getPublicKey(), $signedBlock);

Reject revoked tokens

$token = Biscuit::fromBase64("<base64 string>", $publicKey);

// revocationIds is a list of hex-encoded revocation identifiers,
// one per block
$revocationIds = $token->revocationIds();

if (containsRevokedIds($revocationIds)) {
    // reject the token
}

Query data from the authorizer

use Biscuit\Auth\Rule;

$authBuilder = new AuthorizerBuilder();
$authBuilder->addCode('resource("file1")');
$authBuilder->addCode('operation("read")');
$authBuilder->addCode('allow if user($id), right("read")');

$authorizer = $authBuilder->build($token);
$authorizer->authorize();

$results = $authorizer->query(new Rule('u($id) <- user($id)'));
foreach ($results as $fact) {
    echo $fact . "\n";
}

Authorizer snapshots

Authorizer state can be serialized for inspection or persistence:

// save
$snapshot = $authorizer->base64Snapshot();

// restore
$restored = \Biscuit\Auth\Authorizer::fromBase64Snapshot($snapshot);