I'm using Django REST framework JWT Auth for session creation and permissions, the only problem is: when I log in and after the token expires I can't continue doing the operation I want, unless I log in again. And I didn't fully understand the documentations provided for the additional settings.
So can any one explain a method for dynamically creating (and refreshing) my token (following best practices) so that I can keep doing operations when I'm logged in.
P.S: I'm using angular 2 for my front end, and I'm inserting the token in the Http requests headers. Thanks.
Go to Dashboard > Applications > APIs and click the name of the API to view. Locate the Token Expiration (Seconds) field, and enter the appropriate access token lifetime (in seconds) for the API. Default value is 86,400 seconds (24 hours). Click Save Changes.
Set the token expiration to one week and refresh the token every time the user opens the web application and every one hour. If a user doesn't open the application for more than a week, they will have to login again and this is acceptable web application UX.
So in summary when authorization is successful you need to issue two token ACCESS_TOKEN and REFRESH_TOKEN. When ACCESS_TOKEN expires you need to call another api with REFRESH_TOKEN to get new ACCESS_TOKEN. The client application can get a new access token as long as the refresh token is valid and unexpired.
JWT token refresh is a little confusing, and i hope this explanation helps.
issued at
time (iat
in the token)expiration date
(now() + 1 hour, for example)iat
never changes, but expires
does change with each refreshWhen you want to extend a token, this is what happens:
token
to the server endpoint /.../refresh/
now() <= token.iat + JWT_REFRESH_EXPIRATION_DELTA
now() + JWT_EXPIRATION_DELTA
issued at
value in the token does not change
You have EXPIRATION=1 hour
, and a REFRESH_DELTA=2 days
. When you login you get a token that says "created-at: Jun-02-6pm". You can refresh this token (or any created from it by refreshing) for 2 days. This means, for this login, the longest you can use a token without re-logging-in, is 2 days and 1 hour. You could refresh it every 1 second, but after 2 days exactly the server would stop allowing the refresh, leaving you with a final token valid for 1 hour. (head hurts).
You have to enable this feature in the backend in the JWT_AUTH
settings in your django settings file. I believe that it is off by default. Here are the settings I use:
JWT_AUTH = {
# how long the original token is valid for
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=2),
# allow refreshing of tokens
'JWT_ALLOW_REFRESH': True,
# this is the maximum time AFTER the token was issued that
# it can be refreshed. exprired tokens can't be refreshed.
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
Then you can call the JWT refresh view, passing in your token in the body (as json) and getting back a new token. Details are in the docs at http://getblimp.github.io/django-rest-framework-jwt/#refresh-token
$ http post localhost:8000/auth/jwt/refresh/ --json token=$TOKEN
Which returns:
HTTP 200
{
"token": "new jwt token value"
}
I've had same problem in angularjs and I've solved it by writing a custom interceptor service for my authentication headers.
Here's my code:
function($http, $q, store, jwtHelper) {
let cache = {};
return {
getHeader() {
if (cache.access_token && !jwtHelper.isTokenExpired(cache.access_token)) {
return $q.when({ 'Authorization': 'Token ' + cache.access_token });
} else {
cache.access_token = store.get('token');
if (cache.access_token && !jwtHelper.isTokenExpired(cache.access_token)) {
return $q.when({ 'Authorization': 'Token ' + cache.access_token });
} else {
return $http.post(localhost + 'api-token-refresh/',{'token': cache.access_token})
.then(response => {
store.set('token', response.data.token);
cache.access_token = response.data.token;
console.log('access_token', cache.access_token);
return {'Authorization': 'Token ' + cache.access_token};
},
err => {
console.log('Error Refreshing token ',err);
}
);
}
}
}
};
}
Here, on every request I've had to send, the function checks whether the token is expired or not. If its expired, then a post request is sent to the "api-token-refresh" in order to retrieve the new refreshed token, prior to the current request. If not, the nothing's changed.
But, you have to explicitly call the function getHeader() prior to the request to avoid circular dependency problem.
This chain of requests can be written into a function like this,
someResource() {
return someService.getHeader().then(authHeader => {
return $http.get(someUrl, {headers: authHeader});
}); }
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