Search by

plin-code / laravel-platform-authorizer

danielebarbaro

Remote authorization for a vendor panel and signed feature flags in self-hosted Laravel installations

Package info

github.com/plin-code/laravel-platform-authorizer

pkg:composer/plin-code/laravel-platform-authorizer

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v0.1.0 2026-10-01 12:44 UTC

This package is not auto-updated.

Last update: 2026-10-02 01:54:55 UTC


README

Laravel Platform Authorizer

Laravel Platform Authorizer

Packagist PHP from Packagist Laravel versions GitHub Workflow Status (main) Total Downloads

Remote authorization for the vendor panel of a self-hosted Laravel application, and feature flags that only the vendor can change.

You sell a Laravel application that each customer runs on their own server, and you need an area inside it (for instance a panel that switches licensed features on and off) that the customer's staff cannot open, even though they own the server, the database and the .env file. This package closes that area behind a round trip to an authorizer run by the vendor, and keeps the feature flags in a manifest signed by the same authorizer.

  • The application only holds Ed25519 public keys. It never holds a secret, so nothing on the customer's server can forge an authorization.
  • The signed assertion in the session and the signed manifest in the database are verified again on every request. A row edited by hand grants nothing.
  • Every failure closes the door with a generic refusal.

It does not stop someone who edits the source code. See How it works for the trust model and its limits.

Requirements

  • PHP 8.3 or later with ext-sodium
  • Laravel 12 or 13
  • laravel/pennant for the flag driver (optional)
  • livewire/livewire for the component checks (optional)

Installation

composer require plin-code/laravel-platform-authorizer
php artisan vendor:publish --tag=platform-authorizer-config
php artisan vendor:publish --tag=platform-authorizer-migrations
php artisan migrate

The migration creates the feature_manifests table, which keeps the signed manifest of the installation.

Quick Start

1. Configure

Ask the vendor for the authorizer URL, the product slug, the installation slug and the public keys. Give the vendor the callback URL of the installation (https://<your app>/platform-authorizer/callback) and the email of every local user who will open the panel: the assertion is only accepted for a logged in user with the same email.

Write the values in config/platform-authorizer.php, which belongs in version control. Only the installation slug comes from .env:

'url' => 'https://authorizer.example.com',
'product' => 'acme-crm',
'installation' => env('PLATFORM_INSTALLATION'),
'keys' => [
    'acme-2026-1' => 'G1yHmSCN25mB4Cp3WRutDKtJLT5ZXQdTGOAPmLeAA28=',
],
'protected_livewire_namespaces' => [
    'App\\Livewire\\Platform',
],
PLATFORM_INSTALLATION=acme-crm-rossi

Keep SESSION_LIFETIME at 15 minutes or more and the session cookie same_site at lax. See Configuration for every setting and the other gotchas.

2. Protect routes

use App\Livewire\Platform\PlatformPanel;
use PlinCode\PlatformAuthorizer\Http\Middleware\RequirePlatformAuthorization;

Route::middleware(['auth', RequirePlatformAuthorization::class])
    ->prefix('platform')
    ->group(function () {
        Route::get('/', PlatformPanel::class)->name('platform');
    });

Put auth before the middleware: the assertion is bound to the email of the logged in user. A navigation without a valid assertion goes through the authorizer and comes back where it was going.

3. Read and write flags

Register the store in config/pennant.php:

'default' => 'platform-authorizer',

'stores' => [
    'platform-authorizer' => ['driver' => 'platform-authorizer'],
],

Define each flag with its default, then read and write it as usual. Flags are global, and writes go through the authorizer, so they only work inside the protected area:

use Laravel\Pennant\Feature;

Feature::define('check-in', fn () => false); // in a service provider, false unless the manifest says otherwise

Feature::active('check-in');

Feature::for(config('platform-authorizer.global_scope'))->activate('check-in');

The package synchronises the flags every hour through the Laravel scheduler. Run php artisan platform-authorizer:sync-flags once after the first deploy.

Documentation

  • How it works: the problem, the trust model and the limits.
  • Configuration: what to exchange with the vendor, every setting with its default and validation, and the gotchas.
  • Protecting routes: the middleware, the round trip routes, gates (with a Horizon example).
  • Livewire: expired status and grace, protected components, a minimal panel.
  • Feature flags: the Pennant store, defining, reading and writing flags, exceptions, synchronisation.
  • Key rotation: replacing the signing key without downtime.
  • Customisation: the refusal page, translations and locales, publish tags.
  • Protocol: the endpoints, the token format and the claims.
  • Troubleshooting: log messages, refusal reasons and the AssertionRejected event.
  • Testing your application: the FakeAuthorizer helper.

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

License

The MIT License (MIT). Please see License File for more information.