liberusoftware/sessions-devices-api
A Laravel/PHP package that provides API endpoints for managing user sessions and devices, helping you list, inspect, and revoke active sessions or registered devices within your application.
Install alongside its domain module. This package is a presentation adapter — it exposes HTTP endpoints but does not own the session/device business logic. Install it together with the Liberu sessions/devices core module:
composer require liberusoftware/sessions-devices-api
The service provider should be auto-discovered. If not, add it to bootstrap/providers.php (Laravel 11+) or config/app.php.
Look at these first, in this order:
routes/ — this is the real API contract. Run php artisan route:list --path=api to see exactly which URIs, verbs, names, and middleware were registered.config/ — publish anything you find: php artisan vendor:publish --provider="LiberuSoftware\SessionsDevicesApi\SessionsDevicesApiServiceProvider". Config keys usually control route prefix, middleware stack, and guard.src/Http/Controllers and src/Http/Resources — these tell you the response envelope you will be consuming or proxying.composer.json of the package — check which core module/version it requires; a version mismatch is the most common "it installed but returns 500" cause.First use case — "manage my active devices": Authenticate a user, call the device-listing endpoint (typically GET /api/devices or GET /api/sessions), render the list in a SPA/mobile client, and wire a "revoke" action to the corresponding DELETE route. This is the canonical flow the adapter exists for: showing and terminating sessions across devices.
Sanity check before writing any code: create a throwaway test that logs a user in with Sanctum/Passport and hits each registered route. If routes are missing, the provider was not loaded or was overridden by your app's RouteServiceProvider. If routes exist but 500, the domain module is not installed/configured.
Wrap the routes rather than editing the package. Because the adapter registers routes for you, the cleanest integration is usually to disable its route loading (via config flag if available, otherwise by not relying on them) and re-register them inside your own RouteServiceProvider so you can attach your middleware:
Route::middleware(['auth:sanctum', 'throttle:api', 'verified'])
->prefix('api/v1')
->group(base_path('vendor/liberusoftware/sessions-devices-api/routes/api.php'));
This gives you versioning and guard control without forking.
Bind overrides, don't subclass blindly. Presentation adapters commonly resolve a domain service out of the container. If you need custom behaviour (e.g., filter out the current device from the list), bind an implementation of the relevant interface in your AppServiceProvider:
$this->app->bind(
\LiberuSoftware\SessionsDevices\Contracts\DeviceRepository::class,
\App\Repositories\ScopedDeviceRepository::class
);
Check src/Providers/ for the exact contract names before doing this — the package is sparsely documented, so the provider's register() method is your source of truth.
Standardize the response envelope for your clients. If the adapter returns raw models, wrap them in your own API Resource at the boundary, or configure the package's resource class if one is exposed. Consumers of this package (SPAs, mobile apps) benefit from a stable { data, meta } shape so device-list pagination doesn't change under them.
Integration tip — tie revocation to your auth lifecycle. On logout, after $request->user()->currentAccessToken()->delete() (Sanctum), call the adapter's revoke-session endpoint or its underlying service so the device disappears from other clients' lists. Similarly, on password change, revoke all other sessions via the bulk endpoint. The adapter is designed to be the transport for these operations; don't reimplement revocation in controllers.
Testing pattern. Use Sanctum::actingAs($user) and assert the exact JSON structure the adapter emits, plus guard against route regressions:
Sanctum::actingAs($user);
$this->getJson('/api/devices')
->assertOk()
->assertJsonStructure(['data' => [['id', 'name', 'last_seen_at']]]);
Then a separate test asserting $this->getJson('/api/devices')->assertUnauthorized() without auth — middleware misconfiguration is the most common failure and this catches it.
Feature-flag rollout. Since the package has no dependents, treat it as unproven in production. Gate it behind a config flag and your own middleware so you can disable the endpoints without a deploy if the domain module misbehaves.
composer.json./api/sessions or /api/devices, the provider's registration order decides which wins. Run php artisan route:list | grep -E 'sessions|devices' and look for duplicates. Prefer a distinct prefix or explicitly disable the package's route loading.NOASSERTION license. The license field is not a recognized SPDX identifier. Do not ship this to production without legal review of the actual LICENSE file — it may be proprietary, unlicensed, or custom.src/ end to end before relying on it. There are no Stack Overflow answers waiting for you. Budget time for reading controllers, requests, and resources.composer.json and commit your composer.lock; don't use * or dev-main.php artisan config:clear && php artisan route:clear (and re-cache in deploy). Stale route caches are the #1 cause of "I added auth but it's still public."web stateful guard; token endpoints with sanctum/api. If the adapter hardcodes a guard in its config, override it — otherwise auth()->user() is null inside the controller and you get empty lists or 403s with no obvious error.route:list shows it? (2) middleware group correct? (3) config published and SESSIONS_DEVICES_* env set? (4) underlying domain service bound in the container (app()->bound(...))? (5) check storage/logs/laravel.log for the class name that wasn't found — it almost always points at the missing domain module.src/Providers/, the config file's middleware and prefix keys, and (if present) form requests you can subclass to add validation. Prefer these over forking; a fork means you own maintenance of a package with no upstream community.How can I help you explore Laravel packages today?