djekl
10/13/2015 - 7:32 AM

Laravel Quick Tip: Handling CsrfToken Expiration gracefully

Laravel Quick Tip: Handling CsrfToken Expiration gracefully

Quick tip for handling CSRF Token Expiration - common issue is when you use csrf protection is that if 
a form sits there for a while (like a login form, but any the same) the csrf token in the form will 
expire & throw a strange error.

Handling it is simple, and is a good lesson for dealing with other types of errors in a custom manner.

In Middleware you will see a file VerifyCsrfToken.php and be tempted to handle things there. DON'T! 
Instead, look at your app/Exceptions/Handler.php, at the render($request, Exception $e) function.

All of your exceptions go through here, unless you have excluded them in the $dontReport array at the 
top of this file. You can see we have the $request and also the Exception that was thrown.

Take a quick look at the parent of VerifyCsrfToken - Illuminate\Foundation\Http\Middleware\VerifyCsrfToken. 
You can see from VerifyCsrfToken.php that handle() is the function called to do the token check. In the 
parent class, if the token fails, a `TokenMismatchException` is thrown.

So back in the Handler class, let's specifically handle that type of exception:

    public function render($request, Exception $e)
    {

        if ($e instanceof \Illuminate\Session\TokenMismatchException)
        {
            return redirect()
                    ->back()
                    ->withInput($request->except('password'))
                    ->with([
                        'message' => 'Validation Token was expired. Please try again',
                        'message-type' => 'danger']);
        }   

        return parent::render($request, $e);
    }
    
The code is simple - if the exception is a `TokenMismatchException` we will handle it just like 
a validation error in a controller. In our forms(s), we need to be sure to use the 
$request->old('field_name') (or the old('field_name') helper function) to repopulate. Simply going 
"back" will refresh the form with a new token so they can re-submit.

CAREFUL! - I found that using the http://laravelcollective.com/ Form::open() tag seemed to be 
incompatible with the token - redirect()->back() was not refresh the token for me. This may just be 
something in my code, but when I used a regular html tag it was fine. If this is happening to you, 
try that.