I am implementing JWT authentication in an angular / laravel application and I have a problem updating the token.
Here is the relevant code:
PHP: a laravel-jwt listener that listens for the 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: filter "after":
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: Authenticated Route Filters:
Route::group(['before' => 'jwt-auth', 'after' => 'RefreshToken'], function () { ... });
JS: interceptor that updates localstorage
'use strict'; angular.module('App') .factory('ResponseInterceptor', ['SessionService', 'jwtHelper', '$location', '$q', function (SessionService, jwtHelper, $location, $q) { return { response: response };
This works well, except for one problem (workflow):
- the token expires, but can still be updated.
- angular send http request with expired token to server
- laravel catches the request and updates the response headers with a new token
- laravel blacklist previous token
The problem is that if any request is sent from angular during the extension delay, all thoses requests are rejected from the server, because the token is invalid (blacklisted).
Am I doing something wrong? Can someone point me in the right direction?
What I would like to get is to set the ttl of the token after about 5 minutes and allow the user to update the token during navigation.