httpOnly cookie: check if user is logged in in react-app - node.js

I have a react app and a nodejs server. I set a httpOnly-cookie containing a JWT for authentication. This works. The problem is: I need some logic client-side to check if the user is logged in. When the user logs in, I could store this "state" in-memory (eg. useState), but when the browser reloads, this state is gone (while the cookie is still there).
I'm tried using js-cookie but obviously this won't work because it's a httpOnly cookie.
How can I check - without doing a (test) axios request to my server - if the user is logged in, when opening the react app in the browser?
Edit:
The answer in this question recommends to store the token in LocalStorage, but other resources (lik the discussion in the answer of this question) says cookies are the way to go.
to be clear, I don't need direct access to the token in the cookie, the cookie is send with every axios request ({withCredentials: true}) and it works like expected. But I just need to know if the cookie is set (and so the user is logged in).

There can be multiple approaches for this scenario. What I think you can do.
1 - You can send a http request to check if the JWT is valid on initial app load and whenever app is reloaded (Same thing basically) and then preserve some authentication state inside the app (Context Api or Redux) and this way you control the routes, etc.
2 - Make sure that whenever the JWT is expired you clear the cookie and whenever client receives 401 you refresh whatever authenticated state you have and redirect the user to login page or any page that does not need authentication.

Just to add to the selected answer.
a loading component and an isLoading state will help prevent the split-second showing of authenticated / protected screens. ex, isLoading ? <LoadingComponent /> : <ProtectedComponent />
You can just update the isLoading state when the request finishes, and should the request yield an unauthenticated response code, you can then perform a redirect.

Related

what to do after authenticating the log-in credentials in expressjs?

I was building my chat app and i prepared the login page to authenticate the user logging into the application not the question if what should i do with it, I used POST method to get the credentials and compared it with the database, now how should i send this to the front end page so as to make user logg in and send message by the username they have logged in.
i do not want a piece of code but rather I'd like to have a suggestion on what should i do next and what should i do next, if i just send the plain username into the frontend then i am afraid that users can change its value and pretend that they are someone else.
You don't send it to the frontend page. You never send password or any other sensitive information to the clientside/frontend/browser
The flow is roughly like this.
Frontend has a login form that posts to the server
Server gets the username and password
Server authenticates and creates a session
Frontend gets information that this user is now logged in.
Every action this user takes has to be check on the server side.
You can also check my answer on similar thougt:
VueJS Secure with Auth0 - How is it secure?
Where the author asks:
If I set some variable like isLoggedIn = true or isAdminUser = true,
what stops the user from manipulating the DOM and forcing these values
to true?
The short answer is nothing. You don't do any authentication on the client side. Its ok to have some variables like isLoggedIn or isAdminUser to make the interface make sense but the server code should always to the actual authentication or authorization.

Storing Express session Id in React

I'm having a problem of understanding the steps for authentication using Express session(backend) + React(frontend)..
When a user logs in the server set up a session cookie object with the user id and this way it can identify if the user is logged in or not...
What about the client side? when user logs in and and I generate a token I send it back to the react app and save it in localStorage to use it for every request I make later? I heard that this is not secured.... So I ask you how should I implement that? How can I save the token I get from the server to use it when I make requests later?
One way I can think of is making another get request on server side which returns the session.userId so I can see if thats true then the user is logged in... I'm just trying to figure out how to implement that
thanks!
Browsers implement cookie storage, you don't have to do anything explicit on the client side to maintain the express session. When authentication first happens the server sends a header to the client instructing it to store a cookie and the browser will hold onto that cookie and send it back on all subsequent requests. None of this needs to happen in client scripts (i.e. your javascript code).
You don't need to store cookies in local storage, usually you should not and session cookies will be "httponly", meaning the client scripts are forbidden from accessing them. This is to mitigate the possibility of session stealing in the case of XSS.

ReactJS: reading value from session in Component

What is the common way in React to read value stored in session on server side (express) in React Component?
I have an auth method that stores token in session (on server). For every next action that require an auth token, i can get it on server side, but i would need to have my UI look different for authorized and non-authorized users. How could i do it?
Usually you interact with your server through an API but what you're suggesting is not something you'd want to do. The authentication is usually done on a per-route basis, and the UI would send a key that maybe gets stored in local storage or as a cookie.
For example, you could have all your routes authenticate by requiring the user's "auth cookie". If it is missing, the user is redirected to "sign in" after which the server sends back the auth key and the UI stores it. The UI can then send it with each request using credentials: 'include'.
This is only one of many solutions out there, not really related to React at all but more broadly to UIs. Hopefully this will help your search!
You can get a value from session storage:
const val1 = sessionStorage.getItem("username");
const val2 = sessionStorage.getItem("useremail");

Session and cookies from cross site

I have a front end HTML website that posts requests to a WebApp hosting online. These html pages run locally on any machine. Thus, they are making cross site requests.
I am thinking of saving cookies and validating these cookies in each request that is sent to my WebApp. Is that the best way to go?
Also, when the user goes back and forth from 1 page to another, (and it is required that he is logged in), do i send a request with cookie from the HTML at the start of the page and redirect him to login page accordingly if his cookie is not valid?
Thanks in advance,
The way you are planning to go about seems alright. Ofcourse you will have to think well about how you are going to save your access tokens. I would use an access token with the IP, username and session expiration date encoded in it.
However just checking on page load would not be the best idea since the result of the check could be spoofed. You should sent this acces token with every request for information so your webapp can decide wether or not to reply with information.

How to enforce same origin policy in Express.js?

Suppose I have the following URL route:
app.post('upvote', function(req, res) {
// make a database a call to increase vote count
});
What can I do to prevent others from opening up a console and sending AJAX POST request on www.mysite.com/upvote? I'd like it so that only www.mysite.com is allowed to make that POST request and no one else.
What can I do to prevent others from opening up a console and sending AJAX POST request
Who is "others"?
If others==users of the site... there is nothing you can do to stop them sending whatever requests they like, using the JavaScript console or any other means. You can't trust the client, so you have to have server-side authorisation: requiring that the user be logged into an account, and registering that the account has upvoted so can't vote again.
If others==admins of other sites (by serving script to their users that causes submissions to your site)... it isn't possible for JavaScript on another site to cause an AJAX POST request, or at least not unless you deliberately opt into that using CORS. But it's quite possible for them to cause a POST by simply creating a <form> pointing to your address and submitting it.
This is a classic Cross Site Request Forgery problem. The widely-accepted solution to XSRF issues is to include a secret token as a parameter in each POST (form or AJAX) submission. That secret token is associated with the logged-in state of the user, either by being stored in the server-side session, or replicated in a client-side cookie. Either way an attacker from another site isn't capable of getting hold of a token that is valid for the logged-in user, so they can't fake the request.
You need XSRF protection on all actions that have a direct effect, whether AJAX or form-based POSTs.
I agree with bobince. others is a very general term.
If others belong to other sites (malicious sites on net).
express has csrf middleware to protect from Cross Site Request
Forgery. You can use it to prevent such a scenario. See the API docs
here.
If others are users of your own site
then that is an authentication issue. Every request must be
checked before serving / executing it. You should implement a user
authentication to prevent this situation. I use passport, and
ensure that user is authenticated before I actually run app.post
handler.

Resources