Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oauth2 Server Client Manager Supervisor Laravel Package

spomky-labs/oauth2-server-client-manager-supervisor

Integrates a client manager supervisor with spomky-labs/oauth2-server, helping PHP OAuth2 servers coordinate client management and validation through a configurable supervisor layer. Useful for wiring client storage and lookup into OAuth2 authorization flows.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is part of the older Spomky-Labs OAuth2 framework (pre-League oauth2-server), so treat it as a decorator around a ClientManagerInterface, not a standalone component. The workflow is:

  1. Install it alongside the OAuth2 server core (spomky-labs/oauth2-server, the client manager implementation, and an event dispatcher — typically symfony/event-dispatcher or league/event, since Spomky's supervisor layer is event driven).
    composer require spomky-labs/oauth2-server-client-manager-supervisor
    
  2. Read ClientManagerSupervisor first — it is the only class worth understanding. It implements ClientManagerInterface and delegates every method (getClient, createClient, updateClient, deleteClient, hasClient, etc.) to an injected inner manager while emitting events around the call.
  3. Look at the events directory next. The supervisor's purpose is to broadcast lifecycle events (client created / updated / deleted / retrieved) so other parts of your app (audit logs, cache invalidation, notifications to a customer portal) can react without touching the manager itself.
  4. First real use case in Laravel: wrap your existing ClientManager binding so that every time an OAuth client is created or rotated (API key regeneration, secret rotation, tenant onboarding), you emit a Laravel event or write to an audit table.

Minimal wiring:

$this->app->singleton(ClientManagerInterface::class, function ($app) {
    return new ClientManagerSupervisor(
        new YourClientManager($app['db']->connection()),
        $app['events']            // must satisfy the interface the supervisor expects
    );
});

Implementation Patterns

Decorator chaining. The supervisor is intentionally a transparent proxy. If you already have caching or throttling managers, stack them: Supervisor(CacheManager(SqlClientManager)). Order matters — put the supervisor outermost if you want events to fire on cache misses as well as DB hits, innermost if you only want events on true persistence operations.

Event-to-Laravel bridge. Spomky's dispatcher contract is not Laravel's Illuminate\Contracts\Events\Dispatcher. Use a small adapter class that forwards dispatch() to Laravel's dispatcher, then register listeners in a EventServiceProvider. Typical listeners:

  • ClientCreated → invalidate config cache, ping the tenant's webhook URL.
  • ClientDeleted → cascade revoke of issued tokens (do this in a queued job, not synchronously).
  • ClientUpdated → clear an OPcache/Redis entry keyed by client_id if you front the manager with a cache.

Repository vs. supervisor boundaries. Keep your manager concerned only with storage. Every cross-cutting concern — audit, notifications, cache invalidation, metrics — goes into a supervisor or a listener on a supervisor event. This keeps the storage layer swappable (SQL in prod, in-memory in tests).

Testing. Because the supervisor is just a decorator, you can instantiate it in a unit test with a fake inner manager and an in-memory dispatcher (Spomky ships a simple one) and assert which events fire for each CRUD call. Do not spin up the full container for this.

Rotation workflow. For secret rotation endpoints, call updateClient on the supervisor-wrapped manager so listeners can log the rotation actor and timestamp. Bypassing the supervisor (e.g. writing directly to the oauth_clients table in a migration) will silently skip every hook — this is the most common integration mistake.

Gotchas and Tips

  • This package is effectively legacy. It belongs to the abandoned Spomky-Labs OAuth2 stack (0 dependents, no recent activity). If you are starting fresh in Laravel today, use league/oauth2-server with laravel/passport — Passport already emits its own client events (Laravel\Passport\Events\ClientCreated etc.) with better framework integration. Only adopt this package if you are maintaining an existing Spomky codebase.
  • Interface drift between versions. The supervisor compiles against a specific minor version of ClientManagerInterface. If you bump the OAuth2 server core but not the supervisor, you will get fatal class must implement method errors when the interface gained a signature. Pin the whole Spomky stack together in composer.json and bump as a unit.
  • Events fire before or after? Check the actual source — most Spomky supervisors dispatch after the inner call returns, but some lifecycle events (pre-creation validation) dispatch before. Do not assume; a listener that reads the just-created client will fail if the event is pre-persist.
  • No Laravel service provider is shipped. You must publish your own bindings. The container binding for ClientManagerInterface is the single extension point — everything else in your app should resolve the interface, never the supervisor class directly.
  • Dispatcher contract mismatch is the #1 runtime bug. The package does not accept Laravel's dispatcher; the type hint will reject it. Write the adapter, or inject Symfony's EventDispatcher and re-emit into Laravel events from there.
  • Debugging: enable the dispatcher's profiler / Laravel's Event::fake() in tests to confirm which events actually fire. If Event::fake() shows nothing, the likely culprit is a direct DB call bypassing the supervisor, or the manager being resolved from a stale container binding after config:cache.
  • Config quirks: if you cache config in production, any closure-based binding in a service provider will throw LogicException: Serialization of 'Closure' is not allowed. Move the supervisor construction into a singleton call that reads config values, not closures captured at boot.
  • Extension point worth knowing: the supervisor's constructor signature is the contract you should code against in your own wrappers — build a LoggingClientManager and place it inside the supervisor if you want its logs to carry the same request ID as the events, or outside if you want only user-facing events logged.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel