I am implementing JWT authentication in an angular/laravel application and I have a problem with token refresh.
Here the relevant code:
PHP: the laravel-jwt listener that 'listen' for tymon.jwt.expired event:
    /**
     * Fired when the token has expired
     * @param \Exception $e
     * @return \Illuminate\Http\JsonResponse
     */
    public function expired($e)
    {
        $token = \JWTAuth::parseToken();
        Config::package('tymon/jwt-auth', 'jwt');
        $ttl = Config::get('jwt::refresh_ttl');
        $iat = Carbon::createFromTimestamp($token->getPayload()->get('iat'));
        $now = Carbon::now();
        // if renew ttl is expired too, return 401, otherwise let
        // the application generate a new token to frontend
        if ($iat->diffInMinutes($now) >= $ttl) {
            unset($iat, $now, $ttl);
            return response_failure(
                Lang::get('errors.api.auth.expired'),
                Config::get('status.error.unauthorized')
            );
        }
        unset($iat, $now, $ttl);
    }
PHP: the 'after' filter:
/*
|--------------------------------------------------------------------------
| JWT-Auth token-refresh Filter
|--------------------------------------------------------------------------
|
| The RefreshToken filter update the response headers by returning an 
| updated authentication token.
|
*/
Route::filter('RefreshToken', function($route, $request, $response)
{
    $token = JWTAuth::parseToken();
    try {
        $token->toUser();
    } catch (TokenExpiredException $e) {
        Config::package('tymon/jwt-auth', 'jwt');
        $ttl = Config::get('jwt::refresh_ttl');
        $iat = \Carbon\Carbon::createFromTimestamp($token->getPayload()->get('iat'));
        $now = \Carbon\Carbon::now();
        if ($iat->diffInMinutes($now) < $ttl) {
            $response->headers->set('Authorization', 'Bearer ' . $token->refresh());
        }
    }
});
PHP: The authenticated routes filters:
Route::group(['before' => 'jwt-auth', 'after' => 'RefreshToken'], function () { ... });
JS: The interceptor that updates the localstorage
'use strict';
angular.module('App')
    .factory('ResponseInterceptor', ['SessionService', 'jwtHelper', '$location', '$q',
        function (SessionService, jwtHelper, $location, $q) {
            return {
                response: response
            };
            // called for http codes up to 300
            function response(response) {
                var token = response.headers('Authorization');
                if ('undefined' !== typeof token && null !== token) {
                    SessionService.setToken(token.split(' ')[1]);
                }
                return response;
            }
        }]);
This works well except for one problem (workflow):
The problem is that if any request is sent from angular during the "renewal" delay, all thoses requests are refused from the server because the token is invalid (blacklisted).
Am I doing things wrong ? Can someone point me in the right direction ?
What I'd like to achieve is setting the ttl of the token at about 5 minutes, and allow the user to renew the token while navigating.
This was indeed a bug of the library, corrected now, read here for more informations
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With