Laravel 5 - Logout a user from all of his devices

14.4k views Asked by At

A user is logged in. And he's also already logged in in 3 different computers. Now user changes his password.

I want to do something to log him out from all of his devices. By default if we change password in one device, nothing happens on other devices.

The first thing that comes in mind is to check password in a middle-ware (every request) which is not good and decreases performance significantly.

How can I do this in Laravel 5?

AND what is the best way to do this? How does big sites logout a user from all devices?

5

There are 5 answers

4
dyachenko On

I did something similar. At first I save sessions in Redis. For each login I save session ID after success auth and relate it with user ID (it's array). If user change password you can remove all user sessions except current (using sessions IDs). If user logout you can remove session id from array of user's sessions. (I think you can use MySQL or other storage for saving relation between user and session ID)

for save session ID I use (when user login )

$redis = \LRedis::connection();
$redis->sadd('user:sessions:' . $userId, Session::getId());

for remove sessions ID from array of user sessions (if user logout or manually logout )

$redis->srem('user:sessions:' . $userId, $sessionId);

remove Laravel session (logout user from other device)

$redis->del('laravel:' . $sessionId);

get all session IDs for user

$redis->smembers('user:sessions:' . $userId);

for logout from all devices use loop

$userSessions = $redis->smembers('user:sessions:' . $userId);
$currentSession = Session::getId()
foreach ($userSessions as $sessionId) {
    if ($currentSession == $sessionId) {
        continue;  //if you want don't remove current session
    }

    $redis->del('laravel:' . $sessionId);
    $redis->srem('user:sessions:' . $userId, $sessionId);
}
1
DsRaj On

In the latest version of Laravel 5.6

You can do this from

auth()->logoutOtherDevices();

logoutOtherDevices

More Info

0
Akshay ak On
//Laravel logout user if role changed by admin in active session of user
//1) Create a new middleware that will check if the user's role has been changed and log them out if necessary. Run the following command to generate the middleware:

    php artisan make:middleware CheckUserRole

//2)Open the generated middleware file (app/Http/Middleware/CheckUserRole.php) and implement the handle method. The method should compare the user's current role with the role stored in the session. If they don't match, log out the user. Here's an example implementation:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class CheckUserRole
{
    public function handle($request, Closure $next)
    {
        if (Auth::check()) {
            $user = Auth::user();

            // Check if the user's role has changed
            if ($user->role !== session('role')) {
                Auth::logout();
                return redirect('/login')->with('message', 'Your role has been changed. Please log in again.');
            }
        }

        return $next($request);
    }
}

//3) Register the middleware in the $routeMiddleware array of the app/Http/Kernel.php file. Add the following line to the array:

'role.check' => \App\Http\Middleware\CheckUserRole::class,

//4)Apply the middleware to the relevant routes or route groups. For example, you can apply it to the routes that handle role changes:

Route::middleware('role.check')->group(function () {
    // Routes for changing user roles
});

//5)When an admin changes a user's role, update the user's role and update the role value stored in the user's session. You can accomplish this in your controller or wherever you handle the role change logic. Here's an example:

// Update the user's role
$user->role = 'new_role';
$user->save();

// Update the role value in the session
session(['role' => 'new_role']);

//6) Open the RegisterController located at app/Http/Controllers/Auth/RegisterController.php.

Inside the create method, after the line that creates a new user, add the following code to set the user's role in the session:

// Create a new user
$user = User::create([
    'name' => $data['name'],
    'email' => $data['email'],
    'password' => Hash::make($data['password']),
]);

// Set the user's role in the session
session(['role' => $user->role]);

//7)Next, open the LoginController located at app/Http/Controllers/Auth/LoginController.php.

//Inside the authenticated method, after the line that logs in the user, add the following code to set the user's role in the session: 
//Note: (authenticated method not present by default we need to create it.)

use Illuminate\Http\Request;

protected function authenticated(Request $request, $user)
{
    // Log in the user

    // Set the user's role in the session
    session(['role' => $user->role]);

    // Redirect the user
    return redirect()->intended($this->redirectPath());
}
0
user14891096 On

Invalidating Sessions On Other Devices

Laravel provides a mechanism for invalidating and "logging out" a user's sessions that are active on other devices without invalidating the session on their current device.

First, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession middleware is present and un-commented in your app/Http/Kernel.php class' web middleware group:

'web' => [
    // ...
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    // ...
],

Then, you may use the logoutOtherDevices method on the Auth facade. This method requires the user to provide their current password, which your application should accept through an input form:

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices(request('password'));

When the logoutOtherDevices method is invoked, the user's other sessions will be invalidated entirely, meaning they will be "logged out" of all guards they were previously authenticated by.
0
Amin Shojaei On

From laravel documents:

Invalidating Sessions On Other Devices

Laravel provides a mechanism for invalidating and "logging out" a user's sessions that are active on other devices without invalidating the session on their current device.

First, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession middleware is present and un-commented in your app/Http/Kernel.php class' web middleware group:

'web' => [
    // ...
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    // ...
],

Then, you may use the logoutOtherDevices method on the Auth facade. This method requires the user to provide their current password, which your application should accept through an input form:

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($password);

When the logoutOtherDevices method is invoked, the user's other sessions will be invalidated entirely, meaning they will be "logged out" of all guards they were previously authenticated by.