Saiyan Prince
Saiyan Prince

Reputation: 4020

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,
     ],
];

Upvotes: 6

Views: 27718

Answers (4)

Balwari Ikram
Balwari Ikram

Reputation: 1

Method 1 : Add Meta Tag to your app.blade.php file :

<meta http-equiv="refresh" content="{{ config('session.lifetime') * 60 }}; url=/logout">

Method 2 : with toaster

(function () {
    const idleDurationSecs = 7200;
    const warningDurationSecs = 5400;
    let idleTimeout;
    let warningTimeout;

    const resetIdleTimeout = function () {
        clearTimeout(warningTimeout);
        warningTimeout = setTimeout(
            () =>
                toastr.warning(
                    "Please refresh the page to remain active",
                    "Your session is about to expire",
                    { timeOut: 1800000 }
                ),
            warningDurationSecs * 1000
        );
        clearTimeout(idleTimeout);
        idleTimeout = setTimeout(
            () => document.getElementById("logout-form").submit(),
            idleDurationSecs * 1000
        );
    };

    // Key events for reset time
    resetIdleTimeout();
    window.onmousemove = resetIdleTimeout;
    window.onkeypress = resetIdleTimeout;
    window.click = resetIdleTimeout;
    window.onclick = resetIdleTimeout;
    window.touchstart = resetIdleTimeout;
    window.onfocus = resetIdleTimeout;
    window.onchange = resetIdleTimeout;
    window.onmouseover = resetIdleTimeout;
    window.onmouseout = resetIdleTimeout;
    window.onmousemove = resetIdleTimeout;
    window.onmousedown = resetIdleTimeout;
    window.onmouseup = resetIdleTimeout;
    window.onkeypress = resetIdleTimeout;
    window.onkeydown = resetIdleTimeout;
    window.onkeyup = resetIdleTimeout;
    window.onsubmit = resetIdleTimeout;
    window.onreset = resetIdleTimeout;
    window.onselect = resetIdleTimeout;
    window.onscroll = resetIdleTimeout;
})();

Upvotes: 0

Yasin Patel
Yasin Patel

Reputation: 5731

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.

Upvotes: 8

Arshad Shaikh
Arshad Shaikh

Reputation: 564

please check less than 120 in middleware,ex 115 or 119 in below if condition and then check it

if (now()->diffInMinutes(session('lastActivityTime')) == config('session.lifetime')) {
....
}

Upvotes: 0

Amit Senjaliya
Amit Senjaliya

Reputation: 2945

Need to update the database before logout. Because after logout can't perform $user->update(). so that try following way:

if (auth()->check() && auth()->id() > 1) {
    $user = auth()->user();        

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

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

    //Add Logout method here..
    auth()->logout();

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

Upvotes: 0

Related Questions