Search by

torii / backend

Torii

Backend SDK for torii — verify end-user JWTs without a per-request round trip, manage users from your PHP server.

v0.0.13 2026-08-10 12:06 UTC

This package is auto-updated.

Last update: 2026-09-10 12:56:53 UTC


README

Backend SDK for torii — verify end-user JWTs without a per-request round trip and manage users from your PHP server.

v0.x — API may still change.

Setup

  1. Sign in to app.torii.so and from your dashboard copy:

    • your issuer URL (e.g. https://acme.torii.so)
    • a secret key (sk_test_… for development, sk_live_… for production)
  2. Install the SDK:

    composer require torii/backend

    Requires PHP 8.2+ with the openssl, curl, json, and mbstring extensions.

  3. Verify an end-user JWT:

    use function Torii\Backend\verify_token;
    
    $auth = verify_token(
        token: $bearerToken,
        issuer: 'https://acme.torii.so',
    );
    
    echo $auth->userId, $auth->environmentId, $auth->emailVerified;

    The first call fetches the issuer's JWKS; subsequent calls reuse the cache and rotate keys automatically (handled by firebase/php-jwt's CachedKeySet). No round trip per request. Pass a PSR-6 CacheItemPoolInterface via the cache: argument to share JWKS storage with Redis/Memcached.

  4. Call the backend REST API:

    use Torii\Backend\Torii;
    
    $torii = Torii::create(secretKey: getenv('TORII_SECRET_KEY'));
    $user = $torii->users->get($userId);

Authenticate a request

use function Torii\Backend\authenticate_request;

// PSR-7 ServerRequestInterface, or any framework whose request exposes headers
$auth = authenticate_request($request, issuer: 'https://acme.torii.so');

// Or plain header arrays
$auth = authenticate_request(
    request: ['Authorization' => 'Bearer ' . $token],
    issuer: 'https://acme.torii.so',
);

Laravel

Register the service provider (Laravel 11+ in bootstrap/providers.php):

return [
    // ...
    Torii\Backend\Laravel\ToriiServiceProvider::class,
];

Publish the config and set env vars:

php artisan vendor:publish --tag=torii-config
TORII_SECRET_KEY=sk_live_...
TORII_ISSUER=https://acme.torii.so
# Optional — defaults to https://api.torii.so
# TORII_API_URL=https://api.torii.so

Protect routes with the RequireAuth middleware:

use Torii\Backend\Laravel\Middleware\RequireAuth;

Route::middleware(RequireAuth::class)->get('/me', function (Request $request) {
    return [
        'user_id' => $request->torii_auth->userId,
        'env_id' => $request->torii_auth->environmentId,
    ];
});

On failure the middleware returns 401 with:

{ "error": { "code": "authentication_failed", "message": "..." } }

REST client

use Torii\Backend\Patch;

$page = $torii->users->list(limit: 50);
$user = $torii->users->create(['email' => 'x@y.com', 'name' => 'Ada']);
$torii->users->ban($user->getId());

$sessions = $torii->sessions->listForUser($user->getId());
$torii->sessions->revokeAllForUser($user->getId());

Updating users (tri-state PATCH)

PHP arrays can't natively distinguish "leave this field alone" from "set this field to null", so Users::update() takes an array of Patch instances:

use Torii\Backend\Patch;

$torii->users->update($user->getId(), [
    'name'  => Patch::set('Ada Lovelace'), // update field
    'phone' => Patch::set(null),           // explicitly null on the server
    // omit a key entirely → server leaves that field alone
]);
  • Patch::set($value) — server updates the field to $value.
  • Patch::set(null) — server clears the field (sends JSON null).
  • Omit the key from the patch array entirely — server leaves the field alone.

The REST client is generated by openapi-generator-cli from spec/server-v1.json. To regenerate after a spec change:

npx -y @openapitools/openapi-generator-cli generate \
  -i spec/server-v1.json \
  -g php \
  -o src/Generated \
  --additional-properties=invokerPackage=Torii\\Backend\\Generated,packageName=torii-backend-generated
# Delete docs/, test/, composer.json, README.md, .travis.yml, .openapi-generator/, etc. afterwards.

Tests

composer install
vendor/bin/phpunit

Tests spin up an in-process php -S server that serves a JWKS document signed by a fresh ES256 keypair, then exercise the verifier against it.

License

MIT