Comments (21)
Thinking about this for my own scenario, I wonder if something like the following would work:
var refreshPromise;
jwtInterceptorProvider.tokenGetter = function(config) {
if (refreshPromise) {
return refreshPromise;
}
var token = window.localStorage.getItem('access_token');
if (jwtHelper.isExpired(token)) {
refreshPromise = refreshToken();
return refreshPromise.then(r => {
refreshPromise = null;
return r;
}, err => {
refreshPromise = null;
throw err;
});
}
return token;
}
Re-using the promise created for refreshing the token should let your subsequent requests "queue up" until the token is refreshed, then all the awaiting requests would get the new token.
Caveats: I'm planning on trying this approach, but I'm not sure if the internals of angular-jwt will somehow conflict w/ this idea.
Authors: Thoughts?
from angular-jwt.
thanks to you both -- I know I'll hit this issue again soon
from angular-jwt.
Hey @zbjornson!!
You are definitely right, and actually I had modify like so in my code, but forgot to modify the example. I am fixing my previous comment and the PR I got open to include this in the documentation.
Thank you!
from angular-jwt.
that project finished with an acceptance on the login JWT expiring in 2hrs, rather than auto-renewing
and I’m not using Angular anymore, I’ve moved on to Aurelia
I hope to use JWT again in soon in which case I’ll have another go at starting from your snippet
thanks
al;
On Apr 27, 2016, at 10:47 AM, Pete Johanson [email protected] wrote:
@ajoslin103 https://github.com/ajoslin103 if you want to create a gist of your version and link it here, we can see if we can offer some advise?
—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub #57 (comment)
from angular-jwt.
Appreciate the examples and discussion here!
I had to modify @GabrielGil's approach slightly to store the new promise created by then
, otherwise jwtInterceptor made the http request before the refresh promise had fully resolved (the network request has the header "Authorization: [object Object]")
angular.module('app', ['angular-jwt'])
.config(function Config($httpProvider, jwtInterceptorProvider) {
var refreshPromise;
jwtInterceptorProvider.tokenGetter = ['jwtHelper', '$http', function(jwtHelper, $http) {
if (refreshPromise) {
return refreshPromise;
}
var idToken = localStorage.getItem('id_token');
if (jwtHelper.isTokenExpired(idToken)) {
var refreshToken = localStorage.getItem('refresh_token');
// This is a promise of a JWT id_token
refreshPromise = $http({
url: '/delegation',
// This makes it so that this request doesn't send the JWT
skipAuthorization: true,
method: 'POST',
data: {
grant_type: 'refresh_token',
refresh_token: refreshToken
}
}).then(function(response) {
var id_token = response.data.id_token;
localStorage.setItem('id_token', id_token);
refreshPromise = null
return id_token;
});
return refreshPromise
} else {
return idToken;
}
}];
$httpProvider.interceptors.push('jwtInterceptor');
})
from angular-jwt.
The best thing you can do is refresh your tokens before the expire. That way you will not run into this problem. If you have a 15 min expire, refresh your token at 13 or 14 min.
from angular-jwt.
I've just implemented something as I described in my previous comment, and it seems to work as expected. Multiple "pending" requests get queue'd up if you re-use the promise representing the in-progress refresh, and then clear the saved pending request after the refresh completes.
from angular-jwt.
that looks good, I've been running into the async problem (I've lots of calls all using the jwt) -- I'd be interested in your working solution if you cared to post it.
from angular-jwt.
@petejohanson's solution seems nice to me and works just fine. 💃
from angular-jwt.
@petejohanson -- could you share your final code?
from angular-jwt.
Unfortunately my final solution is more complicated because of other requirements, and is for work so I can't share here. However, the essence of the working version I implemented is exactly like the sample I posted previously.
You would just need to fill in the actual implementation of your refreshToken
function to return a proper promise.
from angular-jwt.
Exactly, well, I just got your idea. My implementation differs as well a little. But the essence of your snippet is the essence of the solution. Thank you again!
from angular-jwt.
Mine didn't work so well -- I'll have to go back and compare it to your direction -- thanks anyway
from angular-jwt.
@ajoslin103 if you want to create a gist of your version and link it here, we can see if we can offer some advise?
from angular-jwt.
@ajoslin103 I can't really share my final code, but this is a modified version of the example shown on the README.md of the repo, and the solution suggested by @petejohanson
This example stamps subsequent calls after a token expired, and resumes then to be sent with the new token after the promise has been resolved. (Thus only one call to the refresh endpoint is performed).
angular.module('app', ['angular-jwt'])
.config(function Config($httpProvider, jwtInterceptorProvider) {
var refreshPromise;
jwtInterceptorProvider.tokenGetter = ['jwtHelper', '$http', function(jwtHelper, $http) {
if (refreshPromise) {
return refreshPromise;
}
var idToken = localStorage.getItem('id_token');
var refreshToken = localStorage.getItem('refresh_token');
if (jwtHelper.isTokenExpired(idToken)) {
// This is a promise of a JWT id_token
refreshPromise = $http({
url: '/delegation',
// This makes it so that this request doesn't send the JWT
skipAuthorization: true,
method: 'POST',
data: {
grant_type: 'refresh_token',
refresh_token: refreshToken
}
}).then(function(response) {
var id_token = response.data.id_token;
localStorage.setItem('id_token', id_token);
refreshPromise = null
return id_token;
});
return refreshPromise;
} else {
return idToken;
}
}];
$httpProvider.interceptors.push('jwtInterceptor');
})
Note the difference with the example on the main page that we store the $http promise in the variable that is gonna be checked on subsequent tokenGetter calls
I really hope this helps ;)
from angular-jwt.
😅
from angular-jwt.
I think @GabrielGil's updates to the README.md should be integrated there, this seems like a common enough need.
from angular-jwt.
I've created a pull request after your suggestions guys (#77) :D
from angular-jwt.
Thanks @petejohanson. Your solution worked for me. My suggestion is to update all examples with the approach described here. Otherwise, you'll get 429 too many requests
. Here are two sources, which require to be updated as they have missing the outer refreshPromise:
https://github.com/auth0/angular-jwt#using-promises-on-the-tokengetter-refresh-token-example
https://auth0.com/blog/2014/10/01/handling-jwts-on-angular-is-finally-easier/
Cheers!
from angular-jwt.
I realized that the backend should return a 200 response code even if token can't be refreshed because the JWT package will loop forever as it isn't expecting a failing request (second parameter of then
method). We're using the JWT package for Laravel and it's implementation returns an exception (401) when the token is completely expired and ready to blacklist. Which philosophy is the right one?
from angular-jwt.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you have not received a response for our team (apologies for the delay) and this is still a blocker, please reply with additional information or just a ping. Thank you for your contribution! 🙇♂️
from angular-jwt.
Related Issues (20)
- Minification problems HOT 2
- urlBase64Decode issue HOT 3
- Restangular not setting the token on requests HOT 1
- Angular 6.0.0 not supporting the Angular JWT HOT 12
- --prod build. Function expressions are not supported in decorators in 'ɵ0' HOT 2
- SSR is failing window doesn't exist HOT 2
- How the Payload will get converted in the JWT Token ? HOT 1
- Breaking changes in latest patch release 0.1.10 HOT 1
- Can't run test suite
- Don't reference actual window HOT 1
- Interceptor can choke on undefined response HOT 5
- Can't inject anything to jwtOptionsProvider tokenGetter config HOT 2
- Routes without jwt authentication are still loading HOT 1
- async TokenGetter doesn't work HOT 1
- Help needed to implement the basic functions HOT 1
- ERROR Error: Uncaught (in promise): TypeError: this.tokenGetter is not a function HOT 2
- Error: Could not get token from tokenGetter function HOT 1
- Bower failed with error: The process 'C:\npm\prefix\bower.cmd' failed with exit code 1
- Create Ivy distribution HOT 1
- Support Ivy distribution HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from angular-jwt.