Laravel csrf token mismatch exception after session timeout

in our application laravel 5, login through ajax. if the user logs off and returns to the previous session, everything is in order. but if the user logs out and remains inactive on this page until the session expires, the user will get an exception csrfTokenMismatchif they try to log in.

I know in verifyCsrfTokenmiddleware, laravel checks if the session matches the csrf token. also in the method Guard.php logout(), the session will be cleared when you log out.

so my questions are:

did the session really turn red when logging out, if so, why can the user still return to the previous session before the session expires?

What happens to the csrf token when the session has expired?

and finally, how is this problem usually handled in an elegant way?

Thanks in advance!

+4
source share
3 answers

This answer applies to version 5.4, possibly to previous versions, but I have not tested them.

The root of the problem is that the CSRF token has expired on the client side, which makes POST on the server with this token.

IF you use AJAX, you can use API routes that do not perform CSRF validation by default.

You can disable CSRF checking for specific URIs. In this case, I will disable the CSRF check for /logout. This approach works well if you really want to exclude specific URIs from validation.

app / Http / Middleware / VerifyCsrfToken.php

/ **
 * The URIs that should be excluded from CSRF verification.
 *
 * @var array
 */
protected $except = [
   '/logout'
];

, CSRF, , . , .

app/Exceptions/Handler.php

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if($exception instanceof \Illuminate\Session\TokenMismatchException){
        // token mismatch is a security concern, ensure logout.
        Auth::logout();

        // Tell the user what happened.
        session()->flash('alert-warning','Your session expired. Please login to continue.');

        // Go to login.
        return redirect()->route('login');
     }

    return parent::render($request, $exception);
}

, , . 1 . , ( 120). , , , POST.

config/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' => 1,

+1

cookie XSRF-Token, 2 ...

TokenMissmatchExceptions , , App/Exceptions/Handler.php:

// ....
use Illuminate\Session\TokenMismatchException;
// ....


public function render($request, Exception $e)
{
    if($e instanceof TokenMismatchException) {
        $uri = \Route::current()->uri();
        if($uri == "login") {
            return redirect()->route('your.login.route')
                             ->withErrors("Login Form was open too long. 
                                           Please try to login again");
        }
    }
    return parent::render($request, $e);
}
0

In your case, I think you will really benefit from using this:

https://github.com/GeneaLabs/laravel-caffeine

I personally handle such situations without an ajax, you can configure it for Ajax requests to return useful json for error handling:

public function render($request, Exception $e)
    {
         if ($e instanceof \Illuminate\Session\TokenMismatchException) {

              return redirect()
                  ->back()
                  ->withInput($request->except('_token'))
                  ->withMessage('Your explanation message depending on how much you want to dumb it down, lol! ');

        }

        return parent::render($request, $e);
    }
}
0
source

All Articles