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.
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)
Maybe it's a silly question but I'm a bit confused about this.
I want to check whether a user is logged in or not but I don't want to use localStorage to save my JWT token. I know that I can easily save it in localStorage and check from there but for my application, I'm sending the JWT token through an HTTP-only cookie from the backend and from the frontend with every request I'm sending this.
So I'm confused if it is in an HTTP-only cookie I can't retrieve this through my script then how can I check the logged-in status except for local storage.
After googling sometimes I got one answer is using the redux-persist library to persist the application state but still under the hood it's doing the same job creating a copy of my state and saving it in local again which I don't want.
Anything else I can do about it or I have to use local storage ( maybe instead of saving the token I can save the user id or some other key: value pair)
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.
I am using Passport-local on Node.js (saving user info in Mongodb) and Angular.js as the client. The process is easy.
However here are 3 security concerns:
When I do the login on the client, a json file with user and real
password are sent to the server.
After I login, the token will be saved in the Web Explorer's local
storage, which can be seen, copied and used in future.
The salt processed jwt token are saved with the username in Mongodb Users Collection, which can be seen and move to another
server (so that we can use the same username and password from
another server to log in and get a new token)
Would anyone like to discuss further about these? Any ideas on how to solve them, and reduce the risk of the website? How about using https?
There is no need to store token in your user schema if you just want to verify your token on other server instances as well. Because, jwt.verify() gives you the functionality to check if the token is valid or not . And if the token valid then you get user info in return which you have used at time of token creation. If you find that user in your database then your token is ok with valid user, otherwise not.
Main thing when creating token is, set expiresIn according to your server demands, so that even if your API security is compromised, it wont be available for long time
Help me pick the right OAuth2 grant type for my Angular App and my REST API?
UX-wise I want just one login form on my front-end, that would ask for username/pass(no dialog asking for permissions). I think the "Resource Owner(Password) Grant" is the most appropriate for me(since I control front&backend), but I'm not sure how should I handle access token refresh.
Correct me if I wrong about the flow:
When user submits credentials through login form, access token is returned.
I can store this token in LocalStorage to make subsequent Ajax requests with it.
As I understand access tokens should be short-lived. And should be updated with Refresh token. Should the refresh token be returned with the access token after initial login and also stored on the client? If not what is the alternative?
Should there be any session maintained on the server to invoke access token refresh? or I should make calls from front-end to refresh the access token when it is about to expire. But then I need a refresh token on the front-end, right?
As you see there is a mess in my head about refresh token. Would be great to have some clarification or suggestion for another grant implementation.
Backend technology I guess is irrelevant here, but just in case it's Symfony2 with FOSOAuthServerBundle.
When you are calling the TOKEN endpoint (for every grant_type possible) on a OAuth Server, you get an access_token but other information as well (I think there are all here):
{
access_token: // your short-lived token
expires_in: // number of seconds before the access_token is invalid
token_type: // the type of the access_token
scope: // scopes of the access_token
refresh_token: // long-lived token to get a new access_token
}
You need, in my opinion, all these information (maybe the scope is unused, but all others will be used later). You have to store the access_token to ba able to make API calls. After seconds, your access_token will not work anymore. You will need to get a new one. You can either ask the user to log in AGAIN or use the refresh_token.
You will have to call the OAuth Server on the TOKEN endpoint but with a grant_type: refresh_token. You will have to provide the refresh_token from the first request (among other information) and in return you will have the same response as above. In fact, I think you will have to do that every time an access_token is expired. In my opinion, the server side does not know anything about sessions or connected users. It knows about valid and invalid access_token.
This is OAuth. If you don't want to have to refresh everytime, you can make a long-lived access_token (by setting the expires_in), I think this is the only solution that makes sens in an OAuth context.
Do you need some clarification about OAuth in general?