What's the proper way of auth system in MERN App? - reactjs

I have built an MERN application
Built an login route and i have 2 JWT tokens one is Access Token and another one Refresh Token
Whats the proper way to store this token in frontend?
I'm setting both the token in http only cookie 🍪
But axios interceptor will send back both the jwt tokens every time in each requests.
So storing in local storage is bad option as i know
What's the proper process? I need refresh token only when access token is expired.
Can anyone please guide me the proper way of doing MERN application?
In every tutorials they setting the http only cookie for access token and refresh token through the response body. In that case how to handle in frontend? Where exactly storing it?

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)

How to get azure ad refresh token with react

I am doing a project with React, msal-react, and msal-browser.
I can get an access token with functions provided with msal-react library, but I cannot get the refresh token manually.
I can see from the network that a token request is performed when user is logged in by redirect, and obviously returned both token and refresh token. However, the refresh token is very well protected and cannot be found under cookie, session storage, or the instance.
Is it possible for the frontend to get refresh token of azure ad?
sorry, I cannot post my code due to security requirements
Refresh tokens are intentionally not returned on the public API surface as MSAL will handle all required token refreshes under the hood when you call acquireTokenSilent. If the backend service needs its own access token it needs to use a server side library such as msal-node. We do not recommend or support obtaining tokens using the SPA library and passing them down to a backend as tokens should only be sent to the resource they are intended for.

I'm authenticating the frontend app, using cookies session, but how to authenticate a user using ReactJS + Springbot?

I have to authenticate users in a scenario that involve a frontend(react) and a backend (springboot).
After working on it I realized that Springboot response include a set-cookie header, but actually the cookie session returned by Springboot is never set in the user-browser, so I asssume the cookie is set in the frontend app, which means that basically the frontend-app is the one authenticated, but no the user, make sense because the frontend is in the end sending the user/password.
How the people approach this scenario usually?, should I have a cookie session as well in the user-browser (so far is my thought)?, should the frontend store something different in the browser to keep track of logged in users?
Ideally I would go with Bearer token based authentication as I could use the backend for mobile applications as well.
Basically you would require to store the JWT in the local storage or key chain.
You could authenticate using JWT token. Get user details from token to use it in front end.
You need to set the session token in the localStorage. After storing it in localStorage you need to check session token on every protected route. If it's same as you have in backend it's good to go. However, if it has expired you need to run your logout api.

What is the flow of using JWT work on the frontend?

I am new to web dev. I built a backend using Django Rest Framework and am using JWT to handle auth.
Now, I want to connect my backend to my frontend in React. But, I am confused how this should be done. Here are my question:
What is the whole flow of requesting and using JWT access and refresh tokens? Like, when should I request a new access token with my refresh token and when should I request a new refresh token? Thanks!
I will make a quick response:
Flow of requesting and using JWT:
A picture worth a thousand words.
The access token is not lasting forever. Whenever it expires, you have to request a new access token with your refresh token.
Refresh tokens can expire, although their expiration time is usually much longer than access tokens. To handle this case, almost all implementations I've seen return a known error code of 'invalid_grant' that you can check for on the client-side and handle by your business. (ex: Show login page...)
Regarding your questions:
What is the whole flow of requesting and using JWT access and refresh tokens?
I don't know you're using what's package about JWT, having too many packages about Django JWT on github (pyjwt, djangorestframework_simplejwt, ...). And Im using pyjwt in my application, because I want to custom my authentication in-app for security.
The workflow:
When FE send request to login/signup APIs, BE generate a token by using JWT, and return that token in the response.
FE store that token on local storage, using it for sending other requests.
BE will take the token by each request from FE to verify. The same as TokenAuthentication of DRF, we must be custom it when using pyjwt. Will verify the JWT token instead.
when should I request a new access token with my refresh token and when should I request a new refresh token?
You can request a new access token after that token is expired.
When you're using djangorestframework_simplejwt you can see the refresh token but in my case (pyjwt), I just need re-generate jwt token again :)
There could be options, but simple flow is next:
You do auth and get access and refresh tokens from a backend and save them as cookies.
You use your access token until you get error 401 because access token has expired
Then you try to refresh your tokens using your refresh token. If you use axios on frontend, good option to write a middleware for this case. This middleware will refresh tokens and repeat a last request. There should be recipes in google.
If success you got new pair of access and refresh tokens and continue your workflow.
If fail, you need to auth again to get tokens.

good approach for integrating jwt auth/refresh token with react app?

LlI found this YouTube vid which provides a good intro to JWT auth tokens and refresh tokens:
https://youtu.be/mbsmsi7l3r4
Now I'm trying to integrate this design with a React app. I can store the JWT in my app Context and then pass it to API endpoints. Each endpoint would include an authenticate hook to validate authentication with the provided token.
I'm thinking that the authenticate hook could generate and return a refresh token if the original authentication token is within 10 seconds of expiration
But with this ^^^ approach, it seems like I would need to possibly return the auth token or refresh token as part of the API endpoint response object so my React app would have the ability to easily get a handle to that refresh token and pass it in to the next API endpoint call
So I'm just trying to postulate a possible design for JWT integration between my React app and Express API. How common is the approach that I described? Is there a better or more elegant way to do this?
When your access token expired, refresh token is used to get a new copy of access token. Both needs to be persisted somehow on client side. You may find useful information here from Auth0.
Note that refresh token can be implemented in a few form. Refer to this SO question.
My JWT workflow is something along these lines:
Get refresh token and access token from Authorization Server
Use access token to access resources from Resource Server
Access token expired, Resource Server refused access and returned an something like unauthorized status
App notified of expired access token, proceed to use refresh token to get new access token from Authorization Server
Repeat
Your Auth server and Resource server may be the same.
Read this from Auth0 thoroughly.

Resources