Search code examples
phplaravelauthenticationsessionlaravel-5.6

Laravel session timeout, extra logout code


Bottom line:

How to logout the user on session time out?


Detailed Question:

I have a Laravel 5.6.* application and the project demands the user to logout whenever the user is idle. I have tried the solutions that are given here, but none of them worked for me.

Then I stumbled upon this post: https://laravel-tricks.com/tricks/session-timeout-for-logged-in-user and made my way through it to no success.


What I want:

Logout the user automatically on session timeout. Before logging out, set is_logged_in attribute to false or 0 on the Users table. How do I achieve this?


Code that I have tried so far:

session.php

/*
 |--------------------------------------------------------------------------
 | Session Lifetime
 |--------------------------------------------------------------------------
 |
 | Here you may specify the number of minutes that you wish the session
 | to be allowed to remain idle before it expires. If you want them
 | to immediately expire on the browser closing, set that option.
 |
 */

 'lifetime' => env('SESSION_LIFETIME', 120),

 'expire_on_close' => false,

SessionTimeOut.php Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use App\Traits\CacheQueryResults;

class SessionTimeOut
{
    use CacheQueryResults;

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // session()->forget('lastActivityTime');

        if (! session()->has('lastActivityTime')) {
            session(['lastActivityTime' => now()]);
        }

        // dd(
        //     session('lastActivityTime')->format('Y-M-jS h:i:s A'),
        //     now()->diffInMinutes(session('lastActivityTime')),
        //     now()->diffInMinutes(session('lastActivityTime')) >= config('session.lifetime')
        // );

        if (now()->diffInMinutes(session('lastActivityTime')) >= (config('session.lifetime') - 1) ) {
            if (auth()->check() && auth()->id() > 1) {
               $user = auth()->user();
               auth()->logout();

               $user->update(['is_logged_in' => false]);
               $this->reCacheAllUsersData();

               session()->forget('lastActivityTime');

               return redirect(route('users.login'));
           }

       }

       session(['lastActivityTime' => now()]);

       return $next($request);
    }
}

Kernel.php

/**
 * The application's route middleware groups.
 *
 * @var array
 */
 protected $middlewareGroups = [
     'web' => [
         \App\Http\Middleware\EncryptCookies::class,
         \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
         \Illuminate\Session\Middleware\StartSession::class,
         // \Illuminate\Session\Middleware\AuthenticateSession::class,
         \Illuminate\View\Middleware\ShareErrorsFromSession::class,
         \App\Http\Middleware\VerifyCsrfToken::class,
         \Illuminate\Routing\Middleware\SubstituteBindings::class,
         \App\Http\Middleware\SessionTimeOut::class,
     ],
];

Solution

  • You are comparing session lifetime same as in middleware.

    That Means when session will expire, your middleware will not(never) called.And user will move to login page.

    If you want to save entry in Database, You can set long-time session lifetime, and in middleware use your custom time to logout.

    Change in config/session.php

    'lifetime' => 525600, // for one year, it will be in minute, use as you want. 
    

    Change in middleware as below, log out after two hours.

       if (now()->diffInMinutes(session('lastActivityTime')) >= (120) ) {  // also you can this value in your config file and use here
           if (auth()->check() && auth()->id() > 1) {
               $user = auth()->user();
               auth()->logout();
    
               $user->update(['is_logged_in' => false]);
               $this->reCacheAllUsersData();
    
               session()->forget('lastActivityTime');
    
               return redirect(route('users.login'));
           }
    
       }
    

    By this way your session will not expire automatically and you can manipulate data.