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
Related
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.
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!
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.
I am using client-flow authentication in Xamarin.Forms and am trying to figure out how to handle when an authentication token expires.
My Code:
Upon initial login, the user logs in with the native Facebook SDK and I pass the access_token to MobileServiceClient to get back an authenticated user.
var user = await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token).ConfigureAwait(false);
I then save the user's UserId and MobileServiceAuthenticationToken in local settings (using the Xam.Plugins.Settings plugin).
The next time the user opens the app, I set the user from settings and skip manual login:
if (!string.IsNullOrWhiteSpace(Settings.AuthToken) && !string.IsNullOrWhiteSpace(Settings.UserId))
{
client.CurrentUser = new MobileServiceUser(Settings.UserId);
client.CurrentUser.MobileServiceAuthenticationToken = Settings.AuthToken;
}
My Question:
This works great. However, I know that the MobileServiceAuthenticationToken has an expiration on it. What will happen in my app when the expiration date is reached? How do I refresh the token without requiring the user to re-log-in to Facebook? I have tried the MobileServiceClient's RefreshUserAsync() method, but I get the following exception:
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: Refresh failed with a 400 Bad Request error. The identity provider does not support refresh, or the user is not logged in with sufficient permission.
Is there a way to test this? (since the token expiration is 3 months from now.) Thanks for the help!
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: Refresh failed with a 400 Bad Request error. The identity provider does not support refresh, or the user is not logged in with sufficient permission.
Since you are using client-flow authentication, you could not use RefreshUserAsync() for refreshing the MobileServiceAuthenticationToken. Your mobile backend does not cache the related access_token and refresh_token for renewing the authentication Token.
Is there a way to test this? (since the token expiration is 3 months from now.) Thanks for the help!
AFAIK, the MobileServiceAuthenticationToken expiration is one hour by default, you could use https://jwt.io/ to decode your token and check the exp property, then use https://www.epochconverter.com/ to convert your timestamp to human date.
For your requirement, you could follow adrian hall's blog about Caching Tokens and refer to the IsTokenExpired method for decode your authenticationToken and check the exp, then manually renew the authenticationToken.
Per my understanding, there are two approaches for you to achieve your purpose:
You need to cache the facebook access_token in your mobile client side, after you manually checked the authenticationToken and found that it expired, then you could manually execute the following code for renewing the token and explicitly update your local cache.
var user = await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token).ConfigureAwait(false);
Note: Your facebook access_token has the Expiration Date, so if your access_token expired, then you need to force the user to log into Facebook again before acquiring the new authenticationToken.
Or you could build your custom endpoint for refreshing the authenticationToken and explicitly set a long lifetime for your new authenticationToken, details you could follow this similar issue. Note: For your client-side expiration processing, you need to renew the token before your local authenticationToken is about to expire.
I have an MVC4 web application that uses LinqToTwitter to display Tweets when a user's profile page is visited, if they have a Twitter handle.
For this I use ApplicationOnlyAuthorizer:
var auth = new ApplicationOnlyAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = "twitterConsumerKey",
ConsumerSecret = "twitterConsumerSecret"
}
};
auth.Authorize();
My problem is that I have found that auth.IsAuthorized always returns false, even when I have call Authorize() and am successfully able to make calls to Twitter. And also, I have found that if I call Authorize() in every call made to Twitter, that an unhandled exception is thrown if I repeat the call enough times.
It seems quite important that I am able to know if auth is authorized before I make the call to Twitter. For now, I have put in a quick fix where I store my own IsAuthorized Session variable - but am not sure how reliable this is, because the Session variable could outlive the actual authentication itself?
Any advice on this would be appreciated.
The first time you authorize, Twitter will return a bearer token. After Authorize, you can grab this from the auth.BearerToken property. On subsequent calls, you can re-use the same bearer token. The bearer token doesn't expire, unless you invalidate it. Twitter's recommendation is that you use the bearer token for about 15 minutes and then re-authorize after that.