We are using IdentityServer4 and have an issue on using refresh token.
Here is my client configs:
Grant Types:
client_credentials
hybrid
Access token lifetime:
60
Identity token lifetime:
900
Absolute refresh token lifetime:
240
Sliding refresh token lifetime:
60
Refresh token usage:
OneTimeOnly
Refresh token expiration:
Absolute
I am checking access token life time and when it is about to be expired I use refresh token to get new access token. After 240 second the access token life time does not extension and my client goes to Identity Server and it issues new set of tokens for my client.
I want my user enter username/password after expiration the refresh token buy Identity Server issue new tokens instead of asking credential.
Any Idea?
If I'm understanding correctly you want to force the user to interactively authenticate from your client? If so the max_age=n or prompt=login authorize endpoint parameters can be used to trigger that flow and then you can validate the auth_time claim within your client to ensure it's recent enough.
Currently this is happening without prompting because the user still has a valid IDP session via the authentication cookie. I'd recommend using the above method over and above setting the IDP session to be aligned with your client application session lifetime.
Related
I am using a JWT authentication scheme for my app. I did some research about how to store and use access and refresh tokens, and I have several questions that I couldn't really find an answer to. For the app, I am using React for the frontend and .NET 6 Web API for the backened.
Question 1: Storing what where?
Based on the research I did, local storage is not a good place to store a jwt token for security reasons. So probably the second best alternative would be HttpOnly cookie for the jwt token and local storage for the refresh token. However I did read some articles where jwt token is stored in local storage while the refresh token is stored as HttpOnly cookie. Which approach is better, and the pros and cons of each. P.S I will be rotating the tokens, i.e a new access and refresh token will be generated once the old jwt token is refreshed. Or even store it in memory such as redux state
Question 2: When to refresh JWT Token?
Should the jwt token be refreshed just before it expires, such that the backend can verify the token, or is it fine to refresh the token after it expires (by bypassing the verificatoin when refreshing the token only i.e the refresh endpoint). Also should refreshing, be done by setting an timer/interval, or waiting for a request to fail?
Question 3: Accessing User Data and Expiry Date
I am storing some user data, such as username and password in the jwt token so I can acees them in the frontend. The problem is that when setting the jwt token as HttpOnly cookie, since Javascript can't access the token, I won't be able to access user data and the token's data(such as jti and expiry date). For the user data, I could do a seperate request to access user data such as username and email, but for the JWT token's expiry date, how could I obtain it?
I would appreciate answers to these questions or any feedback if someone faced similar issues and how you resolved them
Consider these as discussion rather then guideleines
Question 1: Storing what where?
Storing access tokens in memory is a good choice
But if you have a refresh token, and you need to do a silent login, local storage is the only choice
but you can always encrypt the token before storing
Question 2: When to refresh JWT Token?
if you wait for token to expire and then refresh with refresh token then existing request which failed with expired token need to be queued again.
if you refresh token on regular intervals, if existing token is invalidated with refreshing, then again the same issue failing requests needing to be queued again.
if you are using axios, you can use libraries like axios-auth-refresh, which will queue the failed requests and try then again with a new token.
you can check their source code or may be create your own version if handling failed calls is important.
Question 3: Accessing User Data and Expiry Date
Access token and cookies should not contain sensitive information
its better to make another call to the api to get users info
Question 1: Storing what where?
First, it is never recommended to use refresh tokens if you are not able to store them securely. Consider building a traditional web app instead.
Second, session storage is always recommended over local storage for these types of tokens.
However, I understand the problem and there are ways to get around this with “Secure SameSite Cookies” if both your apps use the same domain name. OWASP has recommendations, have a look at “token side jacking”: https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html
A simplified version below (please read OWASP recommendation and make the necessary adjustments):
During the authentication face (Web API):
create a “user context”, a random string
set access token with “user context”
set refresh token with “user context”
set http response header with a hardened cookie (flags: HttpOnly + Secure + SameSite + cookie prefixes). Value: “user context”
You need to implement validation of “user context” for API requests and for the refresh token flow; if “cookie user context” does not match “token user context”, then respond with proper http error code.
This makes it possible to:
store access token in session storage
store refresh token in local storage
Question 2: When to refresh JWT Token?
Should the jwt token be refreshed just before it expires, such that the backend can verify the token, or is it fine to refresh the token after it expires (by bypassing the verificatoin when refreshing the token only i.e the refresh endpoint).
If access token has expired then try refreshing tokens using your refresh token. If refresh token has expired, then a new authentication is needed. The definition of an expired token is that it is no longer valid and cannot be used.
Also should refreshing, be done by setting an timer/interval, or waiting for a request to fail?
Wait for the request to fail. If both access token and refresh token has expired, then a new authentication is needed.
Question 3: Accessing User Data and Expiry Date
It is not recommended to store sensitive information in access token. The access token should be opaque to the client application. Set access token with some identifier and create a /userinfo endpoint that returns information about the user. Eg, Create an authController with two actions:
/token (used for authentication)
/userinfo (used for retrieving information about the user)
My team is working on implementing or rather configuring B2C login for our client's mobile app. We got the configuration setup to a point where the user can login to the app once and the token gets cached in MSAL. And next time onwards, the user is able to directly login without entering his/her credentials. We are following the pattern as described here
Our code first tries to retrieve the token using AcquireTokenSilent and if the token is not present in the MSAL cache, then we retrieve it using AcquireTokenInteractive.
I was trying to understand how the ID and Access tokens are refreshed and found on MS docs here about tokens which says
Refresh tokens are used to acquire new ID tokens and access tokens in
an OAuth 2.0 flow. They provide your application with long-term access to resources on behalf of users without requiring interaction with those users...
This also mentioned that when we redeem the refresh token to get new ID and Access tokens, we also get a new refresh token that replaces the previous refresh token.
Now I tried logging out and log back into my mobile app after 1 hour or more and I was still able to login. When I inspected the claims, the ID and Access token expiry was refreshed to next 1 hour of login.
My question here is:
Since ID token and Access tokens have default expiry to 1 hr, then how is it that even though I was logged out for more than an hour, my token refreshed and I was able to login without entering user credentials.
If this is because refresh token automatically refreshes the ID and Access tokens when they approach their expiry, then does this process go on till the refresh token expires itself.
The MS docs also mentioned that when the ID and Access tokens are regenerated after their expiry, we also get a new refresh token. If this is the case then the refresh token would never expire since the new token will always have new expiry.
Is there a way to control the refresh token so that we can control when to refresh the ID and Access tokens.
I am sorry if I missed anything but I am a little confused on how the refresh token works and is there a way to control when to refresh the tokens and when not.
Thanks in advance.
Yes, the refresh token is used to get the new id token and access token, even the id token and access token were expired, as long as the refresh token does not expire, it could use the refresh token to get new id token and access token, meanwhile, a new refresh token will be generated, if you want to configure the token lifetime, you could do that in the portal.
Reference - https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-tokens?pivots=b2c-user-flow
I have an implementation of IdentityServer4 which connects with Azure AD for authentication (OIDC). In the callback method, using the IdentityServertools, I am generating the access_token and redirecting the user to SPA with the same. The SPA then stores the access_token into localstorage and uses it for authentication.
Normally, when my SPA app hits the token endpoint of the IdentityServer4, it gives access_token and refresh_token and then uses refresh_token to re-authenticate a returning user.
In this case of SSO with Azure AD, do I need to generate refresh_token manually? If yes, I can build on top of default implementation and that's not the problem (However, the docs suggest against of changing the IRefreshTokenService implementation or building something from scratch)
My real question is, is there a need of refresh_token here? Because refresh_tokens are stored in DB and never get's deleted and after sometime, these refresh_tokens table will swell (right now it already has 80k rows). The user is expected to click on a small tile inside SAP's Successfactor - that will open the signin/consent screen of Azure or will directly take the user to the main page where zhe will just answer a question and done. So it's hardly 2-3 mins business. So I can continue to generate access_tokens from my IdentityServer4 for every click as I don't expect the user to stay authenticated in the browser if zhe has logged out from SAP's Successfactor (or any other app linked with Azure).
Please advise, if I should generate refresh_token? Is it a good architecture?
Access token is used to prove the request is allowed to access the resource(such as api from ms or your custom api) and refresh token is used to refresh access token to make sure the access token isn't expired. Access token will expire in an hour by default and refresh token has 90 days.
At this point, we can easily find the refresh token is designed for some special scenarios because the expired time for refresh token is much longer than access token's expired time, but we can also generate a new access token in other way such as using msal or sign in again.
As you said in the question, you can generate an access token by one click and you don't expect users to stay authenticated for a long time. So I think it's unnecessary for you to use refresh token.
Currently the scenario is. When I am trying to access my app,it first sends my app to Microsoft login page and after successful login it returns a id token which is used to retrieve the data from backend server. Now the expiry time of token is approx 1 hr. Now when this token expires, Microsoft issues a new token(JWT Token), it not redirects me back to login page.
But ideally it should be redirected to login page, as in implicit flow, there is no refresh token. Then on what basis it is issuing a new token ?
I am using Microsoft adal library in my front end side for authentication.
here's the link: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#refreshing-tokens
The implicit grant does not provide refresh tokens. Both id_tokens and
access_tokens will expire after a short period of time, so your app
must be prepared to refresh these tokens periodically. To refresh
either type of token, you can perform the same hidden iframe request
from above using the prompt=none parameter to control the identity
platform's behavior. If you want to receive a new id_token, be sure to
use id_token in the response_type and scope=openid, as well as a nonce
parameter.
We are doing an Html5 AngularJS application. We are using token based authentication. The authentication process logs the user in then a JWT Token is returned to the application which is stored in sessionStorage.
We requested a security audit on the application and the tester said that it is a big problem that the token is stored in the sessionStorage. Because he can copy the token and impersonate a user from another device.
Where and how should I store this token to make sure that it is secure ? Is it even a risk leaving it in the session storage since the hacker would need access to the actual device to perform this attack
regards
One way to increase security on token storage is to store the token in a Cooke with the HttpOnly flag set. This would mean the token could only be accessed when your app makes http requests.