How to get Access Token after login with IdentityServer4 - identityserver4

I want to store Access Token after login to memory cache so that I can validate token on every request and deactivate it when user logout (currently the token is not removed after logout).
I have searched and tried some solution but they didn't work.
Could anyone give me some advices to get token and how to validate it? Thanks

One option is to use IdentityModel.AspNetCore together with a SessionStore in AddCookies, just like this picture below shows:
The SessionStore in AddCookies can then cache the tokens in memory, instead of as by default storing the tokens inside the cookies.
As an alternative you can add an EventHandler to AddCookies that triggers each time a request arrives and there lookup if a token should be disabled.
The alternative is to use Reference tokens with IdentityServer, then the API's receiving the tokens must ask IdentityServer on each request if the token is valid or not.

Related

Access Tokens, Refresh Tokens, And User Data

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)

Refreshing token with on-behalf-of flow (single-sign-on with Teams)

I have a single-sign-on scenario with Microsoft Teams. See full description in the documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/auth-aad-sso
I am getting an access token by "trading" the "teams" token for an access token.
My question is, how do I refresh this access token? In single-sign-on scenario the "refrehs_token" is not returned (?), so normal OAuth2 refresh flow does not seem to be possible.
Imagine I traded it once, and got the access token that expires in say 2 hours. I use it to access graph API (or whatever), and then the token expires.
What should I do to get a new access token? Can I just ask Teams for a fresh "teams" token and trade it again in case the old one expired? Teams App takes care of refreshing its own tokens, right? When should I do this (when I get "access denied", or just if I see that the token has expired?
Looks like I found the reason - you must pass offline_access as scope request then you get back the refresh_token. That was my issue actually, and it is documented, I just did not read carefully:
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
refresh_token The refresh token for the requested access token. The calling service can use this token to request another access token after the current access token expires. The refresh token is only provided if the offline_access scope was requested.

How to use refresh token coming from acquiretoken silent in MSAL-browser

I am trying to acquire token by aquiretokensilent after login and then have to do authorization in multiple modules.As documentation of MSAL-browser acquiretokensilent will automatically take care of refresh token.In network tab also i am able to see refresh token.But how to use it, does it automatically replace access token or do i need to do something extra and how i can see that refresh token in the console converting to access token after expiry of access token.I have read lot of documents but not got clearity how to use it.
A refresh token is used for renewing an access token or request access tokens with other scopes.
This official doc indicated that how a refresh token renews/requests a new access token and a new refresh token at the base layer.
And yes, you should call aquiretokensilent before API call, if the access token exists and it is not expired, this function will reply the access token to you from local cache directly, if not, it will request a new access token by refresh token from Azure AD.
For details, see this doc.

Where to store the refresh token safely

Where should i save refresh token,
I save it in my DB but when I send expired JWT so when i try to valid I cant get the payload I save there.
Is this safe to decode with atob the JWT so I get the payload and get the username and find in the db the save refresh token.
Because if i save in local storage this is unsafe cause us save there a long live token instead only the JWT(the short live one)
I try to save it cookies but CSRF attack also a problem even if i add the httponly and the secure one
Please correct me if i wrong
EDIT:
I also wanted to ask how i do silent log in,
Is this like i do setInterval for 14m so i get the new token even if the user don't do nothing?
You can choose between memory or cookie. If you can use cookies, then best choice is cookie! CSRF attack dont be success, if you store it in cookies, another site don't have access to another site cookies. And you have access from XSRF attacks too, becose you neve send refrash token to resource server, it's only for auth server.

What is the token validity time when using Graph API

We are actually using GRAPH API to access active directory users and groups from a Jira script.
For that we use the so called "no user authentication" by using Secret Key and Client key after registering an application on Azure AD.
We undertand the following points
Before sending any POST request to Graph API we need to get a valid Token.
The token value is associated to permission in place
If we change the permission, we need to get a new token to include the change
Our question is as below:
First can you confirm that we we state above is correct ?
Does it means that before each request we need to request the token each time to be sure it is valid ?
Is tehre any expiration of a token which is send with each request ?
Thanks for those clarification
regards
When you acquire an access token, the response contains the expiration time.
By default it is one hour.
You only need to get a new token if the one you have has expired/is going to expire soon.

Resources