Refresh token in Spartacus after user does an action - spartacus-storefront

I want to ask if someone knows a possibility to refresh token after user do any kind of activity. Right now token gets created after user logs in but it never get refresh, only if token is expired and user tries to do a request, this functionality can be found in AuthInterceptor but in our current project we automatically log out if expired_at is less than current Date.
Does someone can give me some guidance? I have tried creating another interceptor and call function handleExpiredAccessToken from class AuthHttpHeaderService but no good response, my token tries to refresh many times ending in a loop.
Also we tried refreshing the token 5 minutes before the expiration time and refresh headers for request like follow code:
const stream = this.authStorageService.getToken();
stream.subscribe((tokenData) => {
if(tokenData.expires_at && ( +tokenData.expires_at - 300000 < new Date().getTime())){
this.oAuthLibWrapperService.refreshToken();
}
if(tokenData.access_token){
request = request.clone({
setHeaders: {
Authorization: `${tokenData.token_type || 'Bearer'} ${tokenData.access_token}`,
},
});
}
});
Thanks in advance.

Maybe you can leverage this back-end configuration property: https://help.sap.com/viewer/d0224eca81e249cb821f2cdf45a82ace/2105/en-US/3d3ea6a4d5fa486aa324ce278fa2afc3.html?q=oauthauthorizationserver.tokenServices.reuseRefreshToken
According to the docs, every time the access token expires (and Spartacus automatically refreshes it), the server will generate a new refresh token. I'm assuming this means the validity of the new refresh token will be reset (easy to check).

You can try to setup a silent refresh like in this repo. If you then call the silentRefresh function of the OAuthService class, it will do a refresh of the token in a iframe.

Related

JwtBearerEvents.OnAuthenticationFailed not being called...sometimes

I have an odd problem. I'm new to JWT authentication so it's probably something I'm doing wrong.
I'm testing out the Refresh Token mechanism and it works sometimes but not others because sometimes the JwtBearerEvents.OnAuthenticationFailed event does not fire.
I'm using C# (.NET 7) to build an ASPNET Core WebAPI.
Essentially:
On log in (via an AJAX call) I create a JWT token (expires after 10 seconds) and a refresh token (expires after 10 days) and send each back to the client in a cookie.
Chrome correctly lists both the JWT token and the Refresh Token cookies.
I make further (valid) GET requests via AJAX to the API methods which process and return successfully.
If I make a request just after (but within a second of) the expiry time of the JWT token then the JWT cookie is sent to the API, fails validation and the OnAuthenticationFailed event fires.
The Refresh Token mechanism does its thing and the JWT token and Refresh Token are successfully refreshed. Chrome shows the updated cookies correctly. All brilliant so far.
I make further (valid) GET requests via AJAX to the API methods which process and return successfully.
But...if I make a request a bit longer after the expiry time of the JWT token (only a second or 2 difference to Step 4.) then the JWT cookie is deleted by Chrome and is not sent, so the token validation never occurs, the OnAuthenticationFailed event DOES NOT fire and the Refresh Token process is never called.
User has to log in again because the Refresh Token mechanism didn't happen.
I guess my question is: Is OnAuthenticationFailed the best way to determine if the JWT token has expired, or is there a more reliable way? I've looked online but can't find any resources to explain this.
Is OnAuthenticationFailed the best way to determine if the JWT token
has expired, or is there a more reliable way?
I think you'd better judge from the expiretime,and there's a claim typed of exp indicates the seconds from 1970-1-1 to your token exp time
after you authoried succeeded,you could try to get the claim type of"exp" from httpcontext
app.Use(async(context,next)=> 
{                
var claims = context.User?.Claims;
var exp = claims.FirstOrDefault(x => x.Type == "exp");
await next.Invoke();            
});
Or you could try to check the claim when you validate the token
I think I've found an alternative way of refreshing the tokens which doesn't require the expired JWT cookie to be sent at all.
I'd followed a tutorial which used the JwtBearerEvents.OnAuthenticationFailed event to capture expiry and, as I'm a bit new to this, had to go through it all with a fine toothcomb to work out why it wasn't working.
The client-side code now responds to the simple 401 NotAuthorized status and that kicks of the process to refresh the token, which only requires the Refresh Token cookie to be sent.
Update: Just in case anyone else is stuck with this, in the case where the JWT cookie is removed by the browser due to expiry and therefore doesn't send it, the OnChallenge JwtBearerEvents event occurs instead of OnAuthenticationFailed.

When to update JWT access token with refresh token

I made a Quasar App with an external authentification server. After the login I receive the access and refresh token. The refresh token is not expiring until I press logout. The access token expires after 10 minutes. So since I need the access token to get the data, this is possible for the next 10 minutes after login. Afterwards I have to call an API including the refresh token to get a new access token.
My question is, how can I make sure to always have a valid access token without logging in again?
As a User I expect to login and have access to everything until I logout. And if my App was for example 15 minutes just laying around and then I want to receive data, that's not possible.
Somehow I want to call the refresh token api silently, but when and how?
Is it common to refresh the token at a certain time interval, or on changing a page or every time I want to receive data?
I didn't find an efficient solution yet.
In a boot file I added the refresh token method. So every time the App was started, the token will be refreshed. For iPhone users for example the app won't be closed completely so the init-method will not be triggered until I completely close the App manually.
I guess to refresh the token before every API call is too much. Or is it?
My question is, how can I make sure to always have a valid access
token without logging in again?
You may use Axios response interceptors in the Quasar Axios boot file to check if a response has failed due to expired access token (based on status code eg 401).
axios.interceptors.response.use(
(response) => {
return res;
},
async(error) => {
if (error.response) {
if (error.response.status === 401) {
// Use refresh token here to get new JWT token;
// return a request
return axios_instance(config);
}
}
return Promise.reject(error);
}
);
Hope this helps!

how should I handle an expired JWT

I am new to JWTs and I have a question about it.
I have a web app with React, Node.js, express, using axios for ajax calls and npm jsonwebtokens for the access tokens.
I read a lot about JWT access tokens and refresh tokens but still one thing is not clear to me.
let's say a user logged in, got his access token and a refresh token, the access token will expire in 15 minutes.
What is the best way to go about it ?
set a timeout that will execute an API call to get a new access token after 15 minutes (let's say 14.5 minutes to be on the safe side)
set an interceptor that will check if the token is still valid and if not first get a new token and then continue with the request
is there another way I didn't considered?
If number 1 is the best way how do I handle a page refresh? the way I have it setup right now is when a user is logging in the login function calls a _refreshCountDown function that:
counts the time until the token expiration - with a setTimeout function
execute the refresh_token API call
call it self back again to start a new countdown based on the new expiration time
now if a user refreshes the page the login function is not being called therefore the _refreshCountDown is never being called.
how would you have handle this scenario?
will appreciate any answer
thanks :)

best practices for refreshing access tokens automatically

I'm building a react native app which uses the spotify web api. I'm using the authorization code flow to authorize a user. First I get a authorization code which can be used to obtain an access token and a refresh token. Everything works!
The problem is: an access token is only valid for a limited amount of time. That's where the refresh token comes in. I understand this concept, but I'm breaking my head about how to implement this.
Let's say a users opens the app, requests an access token and uses this for some time. Then, the user closes the app. After 15 minutes, the users opens the app again. The access token has now expired, so I need to request a new access token.
I've come op with several "solutions". Can someone point me to the correct solution?
Solution 1:
Every time the user opens the app, I request a new access token and use this. Problem: when the user uses the app longer than the valid time of the access token, I won't work anymore.
Solution 2:
I use the access token that's stored in the secure storage on every request. When a request comes back with 'access token invalid' (I don't know the exact error code but you guys know what I mean), I request a new access token with the stored refresh token, and then I send the previous command again (with the new access token). But my question here is: can I use some kind of "wrapper function" which checks the response of the request, and if the response is "access token invalid", it automatically requests a new access token and runs the previous request again.
I think certainly correct solution is solution 2,and i think its clear enough.
and for using solution 2 you need somthing like wrapper function,yes its intelligently.
so you should use interceptor:
what is interceptor ?
You can intercept requests or responses before they are handled by then or catch.
in link below there is a good example of implementing refresh token in axios interceptor:
https://gist.github.com/Godofbrowser/bf118322301af3fc334437c683887c5f
I agree that Solution 2 is the best, each time you do a request you can check to see if the Access Token has expired, and if it has then you can request a new Access Token using the Refresh Token as you mentioned and then make your request, in my own project I do this in a FormatRequestHeadersAsync method which calls a CheckAndRenewTokenAsync method where I perform the following check, here shown in C#:
if(AccessToken?.Refresh != null && (AccessToken.Expiration < DateTime.UtcNow))
{
AccessToken = await GetRefreshTokenAsync(
AccessToken.Refresh,
AccessToken.TokenType,
cancellationToken);
}
You can store the Access Token and the Refresh Token and then use something similar to this before you make each request to the API this will refresh your token and then you can store the new Access Token and the existing Refresh Token.

configure congnito refresh token expiration time

In my app, I make a call to getSession if the user refreshes the page or tries to access a client side rout that requires the user to be authenticated.
The problem I am seeing is that the refreshToken never expires.
So I do this:
const currentSession = await authorisationProvider.getSession();
this.setState({ isAuthenticated: currentSession && currentSession.isValid(), busy: false });
But having stepped through the code and if the cachedSession.isValid() call returns false then a call is made to refreshToken which always appears to return new tokens no matter how long I leave it.
Does the refreshToken never expire or can I configure it to expire in an hour or so?
The only way for things to expire is for localStorage.clear() to be called which is obviously not a real solution.
In aws Cognito console under General settings -> App clients tab you can configure refresh token expiration in days with limit 1-3650 days
Reference: Refresh Token expiration