David Xu
David Xu

Reputation: 5597

Laravel: Only allowing one session per user at a time

Is it possible in Laravel 4 to only allow one session per user at a time?

Eg, so if User logs in and already has other Sessions, those other Sessions are cancelled, preferably with a way to alert them why?

I'm using the Redis session driver on Amazon ElastiCache if that helps as well.

Upvotes: 8

Views: 27997

Answers (4)

Nazmus Shakib
Nazmus Shakib

Reputation: 832

This question is much earlier, but someone will be benefited through these easy steps.

The first step is to comment out the:

\Illuminate\Session\Middleware\AuthenticateSession::class, line from App\Http Kernel.php class.

Secondly add this line in your login function just after login attempt successfully and before redirection: \Auth::logoutOtherDevices(request('password'));

That's all.

Upvotes: 3

xAoc
xAoc

Reputation: 3588

Yeah, I did similar for my project.

So, you need add to your user model another attribute in this case: last_sessid.

public function swapping($user) {
    $new_sessid   = \Session::getId(); //get new session_id after user sign in
    $last_session = \Session::getHandler()->read($user->last_sessid); // retrive last session

    if ($last_session) {
        if (\Session::getHandler()->destroy($user->last_sessid)) {
            // session was destroyed
        }
    }

    $user->last_sessid = $new_sessid;
    $user->save();
}

Now, if the user has an active session, and signs in another browser, the first session will be removed.

P.S. Sorry for my bad english :)

Upvotes: 20

Fershark
Fershark

Reputation: 111

For laravel 5.2 after executing the make:auth command you can create the method:public function authenticated(Request $request,User $user) in the AuthController.php and in that method you can do what you want after login. For a single session per user we add to the AuthController at top:

use Illuminate\Http\Request;
use Auth;

And add the function:

public function authenticated(Request $request,User $user){
    $previous_session = $user->session_id;

    if ($previous_session) {
        \Session::getHandler()->destroy($previous_session);
    }

    Auth::user()->session_id = \Session::getId();
    Auth::user()->save();
    return redirect()->intended($this->redirectPath());
}

Remember to add the migration for altering your users table with the session_id column.

Upvotes: 11

David Xu
David Xu

Reputation: 5597

Managed to solve it like this:

Array of SessionIds in Redis (per user)

example: user.sessions.[userid] [ .... ]

in login before filter:

foreach (json_decode($redis->get('user.sessions.$userId')) as $sesId) {
   Session::getHandler()->destroy($sesId));
}

// add session to redis
$redis->set('user.sessions.$userId', json_encode([Session::getId()]));

This way you can also create a numeric session limit, just destroy up to NumActiveSessions - MaxSessions in Redis.

Upvotes: 1

Related Questions