Handling PassportJS authenticated user in the front-end

I am beginning to understand a bit how to work with PassportJS. But I am still unsure about what happens once a user is authenticated.

From what I see from the documentation example, the main strategy is redirect. So once the login is successful users are redirected to the dashboard, else they are redirected to login.
But then how does the front-end get information about the user that is logged in? And does that information stay if the user reloads the page?

I am building an app where login is optional. The dashboard is accessible to all, but some features are only available to logged in users.
I also need the front-end to know who is logged in.

The front-end is built with React, if that matters.

3 Likes

I’m currently working on something similar, the strategy I used was simply to res.send(data). Since I’m using react on the front-end and don’t need redirects, I just look at the data returned and set a local state variable. This is not as secure and you have to wait on a $.post() to return, but it allows you to keep everything one a single page.

2 Likes

Yes, but the problem I have with that is that if the user reloads the page, the local variable will be gone and he will get logged out.

I’m having a really hard time figuring out how to make the user data persist without storing it, unencrypted, in the browser’s local storage (which, from my understanding, is not really secure)

1 Like

Okay, for that you will need to something like express-session.
https://www.npmjs.com/package/express-session

1 Like

Hi @Marie000

@Josh5231 seems to be right in his recommendation. Actually saving in local storage is an option, depending on the way you select to share data between back and frontend.

Two well known ways to pass encrypted (but NOT safe!) data are:

  • Sessions
  • JWT

The last one is currently most popular and possibly more applicable to SPA projects

As far as I understand the reason why SPA is more applicable to SPA projects is that in an SPA project you have (non-sensitive) data in the frontend and you can route in the frontend from the same page. Having to go to the server for more data is not required all the time for a SPA and you never leave that page. In the examples I have seen if you have to go for more data at the backend the JWT is verified using a secret saved in the backend.

On the contrary sessions are produced strictly in the server. Your app requires to go to the server to ask for data to authenticate, re-serialise the session with new data and reload the session every time you route. This would be ok if the project is not a SPA because you will have to go to the server for more data every time you change the page anyway. Based from what I have seen so far it is my understanding that sessions seems to be better than JWT in the no-SPA scenario, giving you more power on each routing than JWT. However this is my personal interpretation, you would prefer to confirm that conclusion.

Hope this helps?

(Disclaimer: I have worked only one project of the FCC backend curriculum only, meanwhile I am studying the topic)

1 Like

Passport works with sessions stored on the server and cookies sent to the browser with a successful login. So when a user is authenticated in your application, a cookie is sent automatically in the response header and a session is stored in your database. Often applications employ a separate high-speed key-value database like Redis to handle storing sessions so that they can be quickly accessed. The cookie stores basic information about the user that can be used to access that user’s information without requiring them to log back in. Cookies are stored by the browser, typically in a txt file and saved so that your users can refresh the page or navigate to other sites without losing authentication. If you’re using express, there are a number of middlewares you want to have present in order to accept cookies and match their data to a user session on the server.

To get the code and modules you’ll need to get sessions and cookies working with passport, here’s a link to the section in their docs:
http://passportjs.org/docs/configure

Seems like there’s some debate online over the security of sessions versus web-tokens. For most projects it seems like either would be fine. The main difference from what I’ve learned is the method used to authenticate users. Sessions store a unique session id for each user which is matched with the information on the cookie. Web-tokens are instead encoded and decoded using a single-encryption key, so there is no need to store a user’s session on the server. Since you’re using a single key, it’s important to use a strong encryption protocol. Sessions have the advantage that if there was a security compromise, you could invalidate specific sessions. For web-tokens, seems like your option would be to change the key, which would affect all user states. One other thing on security I learned is it’s considered a best practice to keep personal/sensitive information out of the cookie/web-token so you’ll want to avoid putting things like full names, emails, and of course passwords in your payload. Hope this helps!

4 Likes

Thanks everyone!

I initially built with tokens because that is what I learned in my Node tutorial. What worried us with tokens was having to store them in local storage. It was our understanding that there was some security risks with that. But I guess that is necessary if we want the user to not have to login every time they refresh the page. But then how would the app know the user is still logged in? :confused: Would the browser somehow send the token as part of its header when doing a get request to get the front-end?
And if users closed and re-opened their browser, they would have to login again, right?

I have done it yesterday, after checking out almost every possible tutorial about authentication using Node Express. After getting the token from the server I save it as cookies and log in. Every time that the user enters another screen I am sending a GET request to check if the session is still available. If not - then I am getting 401 error (unauthorized), deleting the cookie and going to login page.
BTW I am using react for the client side.

2 Likes

I have a question
using passport js in facebook we need to create an app on facebook and it gives us a key, secret.
can I use that key or secret for different fcc backend project or should I create a new app for each project?

@60noypearl

If you’re using a REST API, then the server is stateless, which basically means that server requests happen without knowledge of the client’s state. Now the browser will store the cookie which can be used to authenticate the user with the session on server. Authentication is the process of identifying who the user is. Like when you show your picture ID at the bar, you’re authenticating that you are who you say you are (the picture) and are authorized to order a drink (age 21+). A session is like having your name on the list with the guy at the door so you don’t have to show your ID and wait in line like everyone else.

So the server will save the session which tells the server about the user, but the server doesn’t store the user’s state. That’s something that React can help with in your application. When a user requests and receives information from the server, you store that data in React’s state. In order to persist that data across all views, the data can be stored in high order component and shared as props through your various views.

But what if a user navigates to a different site and then comes back? That will wipe React’s state unless you store that state somehow in local memory. One way to do that is using the localStorage API where you can set and get data. When the user comes to your site, you can check the localStorage to see if their data is still there before grabbing it again from the server. If the data does get wiped, you still have the cookie in the browser that can be used to fetch the data again from the server without having the user log back in again. If the user clears their cookies, then they will have to log back in again.

@mones-cse

Yes, you should create a new app for each project since the app ID and app secret is needed for authentication. Facebook’s API requires a callback URL which matches the project domain in order to provide to provide the token and profile information on the user. If you’re developing locally you will need to temporarily set site URL to localhost to get working on your machine. Here’s the link to make a new app:

https://developers.facebook.com/apps

5 Likes

@Marie000

What worried us with tokens was having to store them in local storage. It was our understanding that there was some security risks with that.

I haven’t a full reference with me right now but there are security issues with ALL of them. Maybe you want to consult the following?

For token saved in local storage one thing you can do is to follow and control expiration times.

But then how would the app know the user is still logged in? :confused: Would the browser somehow send the token as part of its header when doing a get request to get the front-end?

In the case of sessions, a cookie can be implemented. For tokens, local storage is fine. Also session storage if you don’t mind the person to be logged out when the browser is closed.

Read more about their differences here.

For a token, as far as I know this could be added as QUERY of the url when communicating between front- and backend.

Here a video of a camper working on the authorisation/authentication procedure for the voting app - around min 15. I just had a quick look, not sure about his implementation.

Also a quick search (“jwt”) into the HelpBackend Gitter room resulted in the following as first result:
https://gitter.im/FreeCodeCamp/HelpBackEnd?at=56cbfc7295f2abfa55e8340b.

Hope this helps?

2 Likes

@jmcilhargey and @Marie000 Here’s my idea: in the react front-end top component, have a state object that initially looks like {goodUser: false}. We have to set {goodUser: true} when the user explicitly logs in. But now here’s the trick to handle someone who closes the window without logging out and then re-opens the window. Our top component should also have a function like:

componentDidMount(){
//do an ajax call to ask passport.js whether user is authenticated.
const loginStatusFromServer = result_from_ajax_call;
this.setState({
goodUser:  loginStatusFromServer 
});
}

The pro is nothing needs to be saved in the browser by the developer while componentDidMount will only be called ONE TIME , i.e. when the component mounts. What do you think?

Hi @Marie000, did you ever figure out a way to send session information from the backend to the react app? Seems like a lot of other people have run into this issue.