I’m using JWTs for authentication. The token is valid for 1 hour. The app will be a browser based app & ios app. I have around 4 pages (Login, Category search, Product search, confirmation/add to order). Every single one of these pages makes HTTP requests to my back end so I have to have a valid token for each one.
I can think of two solutions
On login, schedule a refresh every 59 minutes. But will this work well for a browser app? Say for example a user leaves their browser open and comes back after 2 hours and starts searching for a product but the token is now expired so the backend is returning an error
Make a refreshToken() function that is called before every HTTP request like
You can improve method 2 by isolating it into a token provider. When the token provider is asked for a token, it can look at the exp claim of the one it has, and retrieve a new one only if needed.
Yeah thats a good idea. What im not sure about is if it will break my app if the token expires in the middle of the searches (example: user begins searching and 10 secs later the token expires while the user is still typing).
Should not be a problem. The token provider service is responsible for ensuring that you always have a valid token, and the authenticated http service will only make requests with valid tokens.
So in the token provider I can just use something like angular2-jwt’s tokenNotExpired() function that returns true or false depending on if the token is in storage and hasnt expired yet… Will it really be this simple?
get token
check if its expired
return true or false
Not quite, because you’ll have to return some future (Promise or Observable) in order to handle the situation where the token was expired and needs to be refreshed.
Thanks I’m going to give this a try right now. What does this line do? rv = Observable.of(this.token);
The documentation says that of Converts arguments to an observable sequence. So you can subscribe to it and stuff? But would there be any point to that?
It makes the return value consistently an Observable, so that the outside world (callers of this function) need not know or care whether the token was cached or needed to be fetched anew.
I just call refresh() before my http calls. However there is one which I am still trying to figure out. Say a user is typing “Hel” in the search bar and the token expires but then they type “l” a call is sent to my API without a token but if they type “o” it sends a call to my API with the token so the token is not getting stored before the call is made. I will post here if I find a solution or why its happening
I don’t see a need for set(), because presumably the only source of valid tokens comes from calls to get() when there wasn’t one at the time. jwtHelper.isTokenValid() needs to be able to handle the situation where it is passed something null or undefined, and consider that invalid. That solves your initialization case, at the relatively small cost that you will hit the backend (perhaps needlessly) if get() is called before the initial storage read resolves. If that is a concern to you, you could guard against it by waiting on the initial read in get().
I finally got a chance to try and implement this and I’m still having the same problem. I tried all the ways you listed! Also the last get() method doesn’t work for me it never even calls the API I have to do it this way
There are three possible states for this.token at the time get() is called:
falsy: null or undefined
truthy yet invalid
truthy and valid
In either of the first two cases, jwtHelper should tell us the token is invalid, and we will follow the if path which calls authHttp.get() (presumably what you mean by “calls the API”). In the third case, we follow the else path with no need to hit the API because our token is valid.
o I logged my token on login and also in the get(): method as the first line and they are different. I also logged the token in the constructor after storage.get() and it says undefined
That’s the nature of the beast. The only place you can put the log and have it have any meaning is inside the then clause right after you have assigned to this.token. Not outside.
its still not working because this.token is storing the token from the last session even when I reload. I guess I have to clear the storage but still if a new token is set on login shouldnt it clear the old one and the constructor in my token provider get the new one from storage?
I really wish you would bother to read the things I write and explain where my assumptions aren’t valid. Again,
Now you are telling me that “a new token is set on login”, so the tokens aren’t just coming from the authHttp.get() call inside get(). If new tokens are coming in from somewhere else, you need to update both storage and the stored token property of the TokenProvider.