Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ PHP bindings for [Biscuit](https://www.biscuitsec.org), a bearer token supportin
- [Biscuit Website](https://www.biscuitsec.org) - Documentation and examples
- [Biscuit Specification](https://github.com/biscuit-auth/biscuit)
- [Biscuit Rust](https://github.com/biscuit-auth/biscuit-rust) - Technical details
- [Upgrading Guide](./UPGRADING.md) - Migration guide for breaking changes

## Requirements

Expand Down Expand Up @@ -94,24 +95,23 @@ composer require ptondereau/ext-biscuit-php
```php
<?php

use Biscuit\Auth\{BiscuitBuilder, KeyPair, AuthorizerBuilder};
use Biscuit\Auth\{Biscuit, BiscuitBuilder, KeyPair, AuthorizerBuilder};

// Generate a keypair
$root = new KeyPair();

// Create a biscuit token
$builder = new BiscuitBuilder();
$builder->addCode('user("alice"); resource("file1")');
$biscuit = $builder->build($root->private());
// Create a biscuit token (can pass code directly to constructor)
$builder = new BiscuitBuilder('user("alice"); resource("file1")');
$biscuit = $builder->build($root->getPrivateKey());

// Serialize to base64
$token = $biscuit->toBase64();

// Parse and authorize
$parsed = Biscuit::fromBase64($token, $root->public());
$parsed = Biscuit::fromBase64($token, $root->getPublicKey());

$authBuilder = new AuthorizerBuilder();
$authBuilder->addCode('allow if user("alice"), resource("file1")');
// Authorizer with inline code
$authBuilder = new AuthorizerBuilder('allow if user("alice"), resource("file1")');
$authorizer = $authBuilder->build($parsed);

// Check authorization
Expand Down Expand Up @@ -141,12 +141,34 @@ $biscuitWithAttestation = $biscuit->appendThirdParty(
);
```

### Parameterized Primitives

```php
use Biscuit\Auth\{Fact, Rule, Check, Policy};

// Fact with constructor params
$fact = new Fact('user({id})', ['id' => 'alice']);

// Rule with params
$rule = new Rule('can_read($u, {res}) <- user($u)', ['res' => 'file1']);

// Check with params
$check = new Check('check if user({name})', ['name' => 'alice']);

// Policy with params
$policy = new Policy('allow if user({name})', ['name' => 'alice']);

// Or use set() method for dynamic values
$fact = new Fact('user({id})');
$fact->set('id', $userId);
```

### Authorizer Queries

```php
$authorizer = $authBuilder->build($biscuit);

$rule = new Rule('users($id) <- user($id);');
$rule = new Rule('users($id) <- user($id)');
$facts = $authorizer->query($rule);

foreach ($facts as $fact) {
Expand Down Expand Up @@ -180,10 +202,9 @@ use Biscuit\Auth\Algorithm;

// Ed25519 is the default algorithm (recommended)
$keypair1 = new KeyPair(); // Uses Ed25519
$keypair2 = KeyPair::newWithAlgorithm(); // Uses Ed25519 by default

// Explicitly use Secp256r1
$keypair3 = KeyPair::newWithAlgorithm(Algorithm::Secp256r1);
$keypair2 = new KeyPair(Algorithm::Secp256r1);

// Key import defaults to Ed25519
$publicKey = PublicKey::fromBytes($bytes); // Defaults to Ed25519
Expand Down
155 changes: 155 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Upgrading Guide

## Upgrading from v0.2.x to v0.3.0

v0.3.0 introduces API simplification changes that consolidate redundant methods and add optional parameters to constructors. This is a **breaking change** release.

### KeyPair Constructor

**Before (v0.2.x):**
```php
use Biscuit\Auth\KeyPair;
use Biscuit\Auth\Algorithm;

// Default Ed25519
$kp = new KeyPair();

// Explicit algorithm required separate method
$kp = KeyPair::newWithAlgorithm(Algorithm::Secp256r1);
```

**After (v0.3.0):**
```php
use Biscuit\Auth\KeyPair;
use Biscuit\Auth\Algorithm;

// Default Ed25519 (unchanged)
$kp = new KeyPair();

// Explicit algorithm now via constructor
$kp = new KeyPair(Algorithm::Secp256r1);
```

**Migration:** Replace all `KeyPair::newWithAlgorithm($alg)` calls with `new KeyPair($alg)`.

---

### Builder addCode Methods

The `addCodeWithParams()` method has been removed. Use `addCode()` with optional parameters instead.

**Before (v0.2.x):**
```php
$builder = new BiscuitBuilder();
$builder->addCode('user("alice")');
$builder->addCodeWithParams('resource({res})', ['res' => 'file1']);
```

**After (v0.3.0):**
```php
$builder = new BiscuitBuilder();
$builder->addCode('user("alice")');
$builder->addCode('resource({res})', ['res' => 'file1']);
```

**Affected classes:**
- `BiscuitBuilder`
- `BlockBuilder`
- `AuthorizerBuilder`

**Migration:** Replace all `addCodeWithParams($source, $params)` calls with `addCode($source, $params)`.

---

### Builder Constructors with Optional Source

All builder constructors now accept optional source code and parameters.

**Before (v0.2.x):**
```php
$builder = new BiscuitBuilder();
$builder->addCode('user({id})', ['id' => 'alice']);
```

**After (v0.3.0):**
```php
// Can still use the old pattern
$builder = new BiscuitBuilder();
$builder->addCode('user({id})', ['id' => 'alice']);

// Or use constructor directly
$builder = new BiscuitBuilder('user({id})', ['id' => 'alice']);
```

**Affected classes:**
- `BiscuitBuilder::__construct(?string $source = null, ?array $params = null, ?array $scope_params = null)`
- `BlockBuilder::__construct(?string $source = null, ?array $params = null, ?array $scope_params = null)`
- `AuthorizerBuilder::__construct(?string $source = null, ?array $params = null, ?array $scope_params = null)`

**Migration:** No changes required. This is backward compatible.

---

### Primitive Constructors with Optional Params

`Fact`, `Rule`, `Check`, and `Policy` constructors now accept optional parameters.

**Before (v0.2.x):**
```php
$fact = new Fact('user({id})');
$fact->set('id', 'alice');

$rule = new Rule('can_read($u, {res}) <- user($u)');
$rule->set('res', 'file1');

$check = new Check('check if user({name})');
$check->set('name', 'alice');

$policy = new Policy('allow if user({name})');
$policy->set('name', 'alice');
```

**After (v0.3.0):**
```php
// Can still use set() method
$fact = new Fact('user({id})');
$fact->set('id', 'alice');

// Or use constructor params directly
$fact = new Fact('user({id})', ['id' => 'alice']);

$rule = new Rule('can_read($u, {res}) <- user($u)', ['res' => 'file1']);

$check = new Check('check if user({name})', ['name' => 'alice']);

$policy = new Policy('allow if user({name})', ['name' => 'alice']);
```

**Constructor signatures:**
- `Fact::__construct(string $source, ?array $params = null)`
- `Rule::__construct(string $source, ?array $params = null, ?array $scope_params = null)`
- `Check::__construct(string $source, ?array $params = null, ?array $scope_params = null)`
- `Policy::__construct(string $source, ?array $params = null, ?array $scope_params = null)`

**Migration:** No changes required. The `set()` method is still available. This is backward compatible.

---

### Quick Migration Checklist

1. **Search and replace:**
- `KeyPair::newWithAlgorithm(` → `new KeyPair(`
- `->addCodeWithParams(` → `->addCode(`

2. **Optional improvements (not required):**
- Use constructor params for builders instead of separate `addCode()` calls
- Use constructor params for primitives instead of separate `set()` calls

### Removed Methods

| Class | Removed Method | Replacement |
|-------|---------------|-------------|
| `KeyPair` | `newWithAlgorithm(Algorithm $alg)` | `new KeyPair($alg)` |
| `BiscuitBuilder` | `addCodeWithParams()` | `addCode($source, $params)` |
| `BlockBuilder` | `addCodeWithParams()` | `addCode($source, $params)` |
| `AuthorizerBuilder` | `addCodeWithParams()` | `addCode($source, $params)` |
42 changes: 17 additions & 25 deletions biscuit-php.stubs.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,9 @@ public function __construct() {}
}

class AuthorizerBuilder {
public function addCode(string $source): mixed {}
public function addCode(string $source, ?array $params = null, ?array $scope_params = null): void {}

public function addCodeWithParams(string $source, array $params, array $scope_params): mixed {}

public function addFact(\Biscuit\Auth\Fact $fact): mixed {}
public function addFact(\Biscuit\Auth\Fact $fact): void {}

public function addRule(\Biscuit\Auth\Rule $rule): mixed {}

Expand Down Expand Up @@ -102,17 +100,15 @@ public function buildUnauthenticated(): \Biscuit\Auth\Authorizer {}

public function __toString(): string {}

public function __construct() {}
public function __construct(?string $source = null, ?array $params = null, ?array $scope_params = null) {}
}

class BiscuitBuilder {
public function build(\Biscuit\Auth\PrivateKey $root): \Biscuit\Auth\Biscuit {}

public function addCode(string $source): mixed {}
public function addCode(string $source, ?array $params = null, ?array $scope_params = null): void {}

public function addCodeWithParams(string $source, array $params, array $scope_params): mixed {}

public function merge(\Biscuit\Auth\BlockBuilder $other) {}
public function merge(\Biscuit\Auth\BlockBuilder $other): void {}

public function addFact(\Biscuit\Auth\Fact $fact): mixed {}

Expand All @@ -124,25 +120,23 @@ public function setRootKeyId(int $root_key_id) {}

public function __toString(): string {}

public function __construct() {}
public function __construct(?string $source = null, ?array $params = null, ?array $scope_params = null) {}
}

class BlockBuilder {
public function addFact(\Biscuit\Auth\Fact $fact): mixed {}
public function addFact(\Biscuit\Auth\Fact $fact): void {}

public function addRule(\Biscuit\Auth\Rule $rule): mixed {}

public function addCheck(\Biscuit\Auth\Check $check): mixed {}
public function addRule(\Biscuit\Auth\Rule $rule): void {}

public function addCode(string $source): mixed {}
public function addCheck(\Biscuit\Auth\Check $check): void {}

public function addCodeWithParams(string $source, array $params, array $scope_params): mixed {}
public function addCode(string $source, ?array $params = null, ?array $scope_params = null): void {}

public function merge(\Biscuit\Auth\BlockBuilder $other) {}
public function merge(\Biscuit\Auth\BlockBuilder $other): void {}

public function __toString(): string {}

public function __construct() {}
public function __construct(?string $source = null, ?array $params = null, ?array $scope_params = null) {}
}

class ThirdPartyRequest {
Expand All @@ -165,7 +159,7 @@ public function setScope(string $name, \Biscuit\Auth\PublicKey $key): mixed {}

public function __toString(): string {}

public function __construct(string $source) {}
public function __construct(string $source, ?array $params = null, ?array $scope_params = null) {}
}

class Fact {
Expand All @@ -178,7 +172,7 @@ public function name(): string {}

public function __toString(): string {}

public function __construct(string $source) {}
public function __construct(string $source, ?array $params = null) {}
}

class Check {
Expand All @@ -191,7 +185,7 @@ public function setScope(string $name, \Biscuit\Auth\PublicKey $key): mixed {}

public function __toString(): string {}

public function __construct(string $source) {}
public function __construct(string $source, ?array $params = null, ?array $scope_params = null) {}
}

class Policy {
Expand All @@ -204,19 +198,17 @@ public function setScope(string $name, \Biscuit\Auth\PublicKey $key): mixed {}

public function __toString(): string {}

public function __construct(string $source) {}
public function __construct(string $source, ?array $params = null, ?array $scope_params = null) {}
}

class KeyPair {
public static function newWithAlgorithm(?\Biscuit\Auth\Algorithm $alg = null): \Biscuit\Auth\KeyPair {}

public static function fromPrivateKey(\Biscuit\Auth\PrivateKey $private_key): \Biscuit\Auth\KeyPair {}

public function getPublicKey(): \Biscuit\Auth\PublicKey {}

public function getPrivateKey(): \Biscuit\Auth\PrivateKey {}

public function __construct() {}
public function __construct(?\Biscuit\Auth\Algorithm $alg = null) {}
}

class PublicKey {
Expand Down
Loading
Loading