Jwt-auth: How can I catch “TokenExpiredException” when token has expired?

Created on 27 Apr 2018  Â·  5Comments  Â·  Source: tymondesigns/jwt-auth

Why I always catch “UnauthorizedHttpException” when the token has expired? How can I catch “TokenExpiredException”??

Most helpful comment

To catch the error globally, go to App/Exceptions/Handler.php and replace render method with it:

    public function render($request, Exception $exception)
    {
       if($exception instanceof \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException){
          return response()->json(["error" => $exception->getMessage()], $exception->getStatusCode());
      }
    return parent::render($request, $exception);
   }

All 5 comments

try it

  try {

    if (! $user = JWTAuth::parseToken()->authenticate()) {
        return response()->json(['user_not_found'], 404);
    }

} catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

    return response()->json(['token_expired'], $e->getStatusCode());

}

See: https://github.com/tymondesigns/jwt-auth/wiki/Authentication

Thanks!

To catch the error globally, go to App/Exceptions/Handler.php and replace render method with it:

    public function render($request, Exception $exception)
    {
       if($exception instanceof \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException){
          return response()->json(["error" => $exception->getMessage()], $exception->getStatusCode());
      }
    return parent::render($request, $exception);
   }

Change the App\Exceptions\Handler.

    public function render($request, Exception $exception) {
        if ($exception instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) {
            return response()->json(["error" => $exception->getMessage()], 401);
        }
        return parent::render($request, $exception);
    }

Here's some example code to wet your mojo:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

class Authenticate extends Middleware
{
    /**
     * Exclude these routes from authentication check.
     *
     * @var array
     */
    protected $except = [
        'api/logout',
        'api/refresh',
    ];

    /**
     * Ensure the user is authenticated.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        try {
            foreach ($this->except as $excluded_route) {
                if ($request->path() === $excluded_route) {
                    \Log::debug("Skipping $excluded_route from auth check...");
                    return $next($request);
                }
            }

            \Log::debug('Authenticating... '. $request->url());

            JWTAuth::parseToken()->authenticate();

            return $next($request);
        } catch (TokenExpiredException $e) {
            \Log::debug('token expired');
            try {
                $customClaims = [];
                $refreshedToken = JWTAuth::claims($customClaims)
                    ->refresh(JWTAuth::getToken());
            } catch (TokenExpiredException $e) {
                return response()->json([
                    'error' => 'token_expired',
                    'refresh' => false,
                ], 401);
            }

            return response()->json([
                'error' => 'token_expired_and_refreshed',
                'refresh' => [
                    'token' => $refreshedToken,
                ],
            ], 401);
        } catch (TokenInvalidException $e) {
            \Log::debug('token invalid');
            return response()->json([
                'error' => 'token_invalid',
            ], 401);
        } catch (TokenBlacklistedException $e) {
            \Log::debug('token blacklisted');
            return response()->json([
                'error' => 'token_blacklisted',
            ], 401);
        } catch (JWTException $e) {
            \Log::debug('token absent');
            return response()->json([
                'error' => 'token_absent',
            ], 401);

        }

    }
}

Here is some Axios interceptors that function along with that middleware:

import axios from 'axios';
import Swal from 'sweetalert2';
import store from '~/store';
import router from '~/router';

/**
 * Request interceptor: for each request to the server,
 * attach the auth token if it exists.
 *
 */
axios.interceptors.request.use(async (request) => {
    try {
        const token = store.getters['auth/token'];

        if (token) {
            request.headers.common.Authorization = `Bearer ${token}`;
        }

        // https://laravel.com/docs/7.x/broadcasting
        // request.headers['X-Socket-Id'] = Echo.socketId()

        return request;
    } catch (err) {
        throw new Error(`axios# Problem with request during pre-flight phase: ${err}`);
    }
});

/**
 * Response interceptor: for each server error response,
 * check if client-side action is needed.
 *
 */
axios.interceptors.response.use(response => response, (error) => {
    if (!error.config) {
        return Promise.reject(error);
    }

    const { config, data, status } = error.response;

    console.log('ERROR RESPONSE', error.response);

    if (status >= 500) {
        Swal.fire({
            icon: 'error',
            title: 'Oops...',
            text: 'Something went wrong! Please try again.',
            confirmButtonText: 'Ok',
        });
    }

    if (status === 429) {
        Swal.fire({
            icon: 'error',
            title: 'Slow down...',
            text: "You've been throttled.",
            confirmButtonText: 'Ok',
        });
    }

    if ((status === 401) && (data.error === 'token_expired_and_refreshed')) {
        store.commit('auth/SAVE_TOKEN', { token: data.refresh.token });
        error.config.headers.Authorization = `Bearer: ${store.getters['auth/token']}`;

        return axios.request(config); // re-try the request
    }

    if ((status === 401) && (data.error === 'token_expired')) {
        store.commit('auth/LOGOUT');

        if (router.currentRoute.name !== 'login') {
            router.push({ name: 'login' }).catch(() => {});
        }
    }

    return Promise.reject(error);
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

loic-lopez picture loic-lopez  Â·  3Comments

marciomansur picture marciomansur  Â·  3Comments

CBR09 picture CBR09  Â·  3Comments

gamelife1314 picture gamelife1314  Â·  3Comments

harveyslash picture harveyslash  Â·  3Comments