pbmedia/laravel-single-session
pbmedia/laravel-single-session limits each user to one active session at a time, automatically invalidating older sessions when a new login occurs. Simple to install and configure, it helps secure Laravel apps against shared or forgotten sessions.
Install with Composer and register the service provider if you are on a Laravel version predating package auto-discovery:
composer require pbmedia/laravel-single-session
The package is archived (last release June 2018), so pin it in composer.json and expect to stay on Laravel 5.5–5.8. First stop is the package's README.md and src/ directory — there is no maintained documentation. Look at the registered middleware and any event listeners in the service provider; that is where the "kill the previous session on login" behavior lives.
First practical use case: add the package's middleware to your web group (or just to authenticated routes) so that when a user logs in from a second device, the earlier session is invalidated. You will almost certainly need the database session driver — set SESSION_DRIVER=database, run php artisan session:table (or use the existing migration), and ensure your sessions table has a user_id column so the package can find and delete the previous session rows.
Minimal checklist:
composer require pbmedia/laravel-single-sessionphp artisan vendor:publishweb groupMiddleware on the web group. The most common integration is appending the package middleware after StartSession and Authenticate in App\Http\Kernel::$middlewareGroups['web']. This gives you single-session enforcement globally with no controller changes.
Scoped to authenticated routes only. If you want anonymous visitors unaffected, apply it as route middleware on your auth route group instead of globally:
Route::middleware(['auth', 'single-session'])->group(function () {
// dashboard, account, etc.
});
Login-event driven flow. The package hooks into Illuminate\Auth\Events\Login (or performs the same work inside middleware). If you need custom behavior — e.g. logging a security event when the old session is killed — listen to the same event in your own EventServiceProvider and record the previous session ID before the package purges it.
Pair with "remember me" deliberately. If you want remember-me tokens preserved while still enforcing one active session, keep Auth::viaRemember() handling intact and test the flow explicitly; the middleware should only invalidate the session, not necessarily the remember token.
Multi-tenant / multi-guard apps. Register the middleware once but make sure your session table's user_id is populated for every guard you care about. If you use separate guards with separate session keys, you will need to verify the package respects them, or wrap it with your own middleware that calls the package's logic per guard.
Testing. Write a feature test that logs a user in via two actingAs sessions (or two HTTP clients with separate session cookies) and assert the first is redirected to login. This is the fastest way to catch regressions if you patch the package.
Fallback pattern. Because the package is abandoned, wrap it: put a thin app-level listener or middleware around it so a future migration to Laravel's native AuthenticateSession + Auth::logoutOtherDevices() is a one-file swap.
Illuminate\Session\Middleware\AuthenticateSession combined with Auth::logoutOtherDevices($password), which is maintained and framework-native.file or cookie drivers it will silently do nothing useful. Database (or a cache store you can query) is effectively required.user_id on the sessions table. Older session:table migrations omit it. If the package "does nothing," check this column first.Log::info('single-session purge', ['user' => $id, 'sessions' => $ids])), then watch storage/logs/laravel.log and query the sessions table directly to verify rows are being deleted.AuthenticateSession.Session::regenerate() on login rather than only deleting old rows — otherwise you are trading one security issue for another.How can I help you explore Laravel packages today?