Blog

13 Dec
2016

Laravel Token Mismatch Exception Icon

Redirect Laravel Token Mismatch Exception error page


laravel TokenMismatchException screen

Every Laravel 5.2 and Laravel 5.4 (UPDATE) developer has at some point seen the above default grey 'TokenMismatchException error page', which is usually caused when a protected page (which the user needs to be logged in to view) has not been refreshed for a long time and the users login session has timed-out. So the best option is to make the url redirect instead of showing this error message

NOTE: There is a slight difference between laravel 5.2 and 5.4 so I have included both versions of the code - $e and $exception.

So have you been wondering if there is anyway to customise the page or redirect to the default login/home page? Well it's actually fairly easy to sort with a few changes to some of the default setting and files.

 Step 1:

The file which needs to be changed is in the following directory 'app\Exceptions\Handler.php'

Add this at the top around line 11, with this we are using the built in Laravel component.

use Illuminate\Session\TokenMismatchException;

Then find the render function and add the following.

Laravel 5.2

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */

public function render($request, Exception $e)
{
    if ($e instanceof ModelNotFoundException) {
        $e = new NotFoundHttpException($e->getMessage(), $e);
    }

    if ($e instanceof TokenMismatchException) {

        return redirect(route('login'))->withError('error_message', 'You page session expired. Please try to login again');
    }

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

Laravel 5.4

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */

public function render($request, Exception $exception)
{
    if ($exception instanceof ModelNotFoundException) {
        $exception = new NotFoundHttpException($exception->getMessage(), $exception);
    }

    if ($exception instanceof TokenMismatchException) {

        return redirect(route('login'))->withError('error_message', 'You page session expired. Please try to login again');
    }

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

So your final amended file should look like this.

Laravel 5.2 Version

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Session\TokenMismatchException;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [
        AuthorizationException::class,
        HttpException::class,
        ModelNotFoundException::class,
        ValidationException::class,
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $e
     * @return void
     */
    public function report(Exception $e)
    {
        parent::report($e);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $e
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $e)
    {
        if ($e instanceof ModelNotFoundException) {
            $e = new NotFoundHttpException($e->getMessage(), $e);
        }

        if ($e instanceof TokenMismatchException) {

            return redirect(route('login'))->withError('error_message', 'You page session expired. Please try to login again');
        }

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

Laravel 5.4 Version

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [
        \Illuminate\Auth\AuthenticationException::class,
        \Illuminate\Auth\Access\AuthorizationException::class,
        \Symfony\Component\HttpKernel\Exception\HttpException::class,
        \Illuminate\Database\Eloquent\ModelNotFoundException::class,
        \Illuminate\Session\TokenMismatchException::class,
        \Illuminate\Validation\ValidationException::class,
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * 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 ModelNotFoundException) {
            $exception = new NotFoundHttpException($exception->getMessage(), $exception);
        }

        if ($exception instanceof TokenMismatchException) {

            return redirect(route('login'))->withError('error_message', 'You page session expired. Please try to login again');
        }

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

    /**
     * Convert an authentication exception into an unauthenticated response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Auth\AuthenticationException  $exception
     * @return \Illuminate\Http\Response
     */
    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        return redirect()->guest(route('login'));
    }
}

 Step 2:

Also on your login page you may want to output the error message so add the following code to your blade view.

@if ($errors->has('error_message'))
    {{ $errors->first('error_message') }}
@endif

 Step 3:

Another option is to extend the default 120 minutes session timeout, so do this by editing the following file 'config/session.php'.

'lifetime' => 120

... and change it to

'lifetime' => 360

I hope this has helped anybody who has experienced the same issue when developing with Laravel.

Posted in: < PHP MVC >
me@grafxflow avatar

me@grafxflow


I am a Full-stack Developer who also started delving into the world of UX/UI Design a few years back. I blog and tweet to hopefully share a little bit of knowledge that can help others around the web. Thanks for stopping by!

Visitors also viewed these posts


Add comment

Add comment