Single Session Login in Laravel

I recently did this.

My solution was to set the session value when a user logs in. Then I had a small class checking if the session ID stored is the same as the current user who is logged in.

If the user logs in from somewhere else the session ID in the DB will update and the "older" user will be logged out.

I didn't alter the Auth driver or anything, just put it on top when the user logs in. Below happens when login is successful:

$user->last_session = session_id();
$user->save();

To check if the session is valid I used below

if(session_id() != Auth::user()->last_session){
   Auth::logout();
   return true;
}

As you can see I added a column in the users table called last_session


What i did in Laravel 5.7 is similar to Somwang's solution, however this will keep the newly logged in user active and logout the old user.

Start with creating a middleware class:

php artisan make:middleware CheckSingleSession

Add the following:

use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Auth;

And write out the handle like this:

public function handle($request, Closure $next)
{

    $previous_session = Auth::User()->session_id;
    if ($previous_session !== Session::getId()) {

        Session::getHandler()->destroy($previous_session);

        $request->session()->regenerate();
        Auth::user()->session_id = Session::getId();

        Auth::user()->save();
    }
    return $next($request);
}

Make sure you also add it in your users migration file:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('firstName');
    $table->string('lastName');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->string('session_id')->nullable();
    $table->rememberToken();
    $table->timestamps();
});

Then you should be able to add it to your routeMiddleware in the Kernel: project\app\Http\Kernel.php

'checksinglesession' => \App\Http\Middleware\CheckSingleSession::class,

(make sure you check the comma's)

And we are done, now you can use it as route middleware. This way there is an active check on single sessions.

Route::group(['middleware' => ['auth' ,'checksinglesession'], 'prefix' => 'app'], function () {
    Route::get('/dashboard', 'DashboardController@index')->name('dashboard.index');
});

With Laravel 5.6 and superior:

in LoginController add method

protected function authenticated()
{
    \Auth::logoutOtherDevices(request('password'));
}

in Kernel

remove comment from line

\Illuminate\Session\Middleware\AuthenticateSession::class,

That's it, the feature is now included in Laravel!