I have an application that uses JWT for user authentication. When a user login in the app, the backend returns an access token and refresh token, my question is:
both tokens must be stored in the same storage/place?
Yes. You will have to store it in the same storage. I'd suggest using something like Secure Store or Async Storage to store your JWT tokens. And when your application is launched, retrieve the access token from Secure Store and store it in memory. Redux preferably, so you don't have to constantly retrieve it from Secure Store each time you make an API call. But, avoid storing the Refresh Token in Redux because you will not use it as often as your access token.
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)
If a user is logged in and his credentials along with JWT token are stored in the local storage. Now if the user after logging in clear the local storage will he be able to still use the application ?
I'm redux to perform all these operations of storing the user creds and token.
Hey depends where you save the token for the sample i you have the token in the cookie I think no.
What I want is to access the customer details in the client side in next.js and I need to pass the customer access token to the backend API. Using next-auth, I was able to store the access token to the session but is it safe or is it better to use the next.js api route and use getToken function? I'm still a beginner in frontend security, I don't know if I'm just being a paranoid but I can't find a topic/post that states it is completely safe.
So by default the session strategy is set to jwt, which means your session is encoded / signed and safe to store sensitive info in.
However, NextAuth.js can be used to automatically put that accessToken you get from your OAuth provider in the JWT token via the jwt callback. Therefore you can pull it out anywhere with the getToken() method you mentioned and authenticate against Google APIs for further use (get drive contents, contacts, etc, etc, etc).
Check out this example for how to do that in the jwt callback: https://github.com/nextauthjs/next-auth-refresh-token-example/blob/57f84dbc50f30233d4ee389c7239212858ecae14/pages/api/auth/%5B...nextauth%5D.js#L67
I've been provided with a REST API which has authentication type bearer (Security Scheme Type: API Key, Header parameter name: Authorization) and which i use to authenticate the user and then fetch other data (i will only create the front end using react).
As a first step the user logs in and i sent his/her username-password to the prementioned REST API and get back an access and a refresh token.
Is anything wrong with storing these 2 tokens in a cookie in order to use them in subsequent requests? How does JWT comes into play regarding these 2 tokens? Is JWT of any use to me in this situation?
There's nothing wrong in storing the tokens in cookies, but if you're planning to have a Single Page Application with React it should be enough to store these tokens in memory. Once the user refreshes the page you can either make them sign in again or perform a silent login in the background to get a new set of tokens. In both cases the session kept on the Authorization Server should kick in and you should get new tokens without the need of user interaction.
Your tokens will be much safer if you don't keep them in cookies.
JWTs are not a requirement for access and refresh tokens. If you don't have to use them I would recommend going with opaque tokens. That said, since you do not have control over the API you might be limited to the format required by the API. If you don't want to be limited by this format you can set up your own gateway which you can use to perform token exchange or introspection and forward requests to the API with proper tokens (something which is called a Phantom Token pattern.
From my understanding of the question, you are using an identity provider which provides you with access token and refresh token for the users. That means it is a authentication as a service REST API at works here.
The REST API requires an authorisation header to be passed along with the username-password to exchange for access token and refresh token for the users. (correct me if I'm wrong) In this case, you might want to keep the authorisation header away from the users (consult the authentication as a service documentation).
You call the REST API with payloads (the user-password) along with headers like this:
Authorization: ACCESS_TOKEN
However the ACCESS_TOKEN is the one provided by the vendor for you to use the REST API. On success call of the REST API, it should return you with a set of access token and refresh token. You can then use this access token and refresh token to safe guard your own API, API that you control to provide service to your users.
The access token and refresh token might just be JWT tokens (again consult the vendor documentation).
Also if you are using an authentication as a service REST API, check the documentation if they provide a client sdk. In that case, it should show you the best practise of handling the access token and refresh token it returned.
I have been trying to add some security to my react app. I am using a JWT token and have been storing it in the local storage. Storing it in the local storage was not very appealing for me and i decided to move the token into react context using the context API. However, after some research i learned that storing the JWT in local storage isn't that bad, and i would still need the token there in order to let the user continue after a refresh.
So, if i am going to be storing the token there anyway, is it worth it to have a context object storing the user as well?
It seems to me that just doing localStorage.get("token") is all i need.
is it worth it?
Both context and localStorage are using the global state, having the same token stored in both places is an anti-pattern.
What I would suggest instead is storing the User information in the context, and the token in the local storage.
Do not store the jwt token in local storage since is vulnerable to XSS attack. So it is better using context API.