DEV Community

Geoffrey Kim
Geoffrey Kim

Posted on • Updated on

Resolving Session Saving Issue for Social Login in NodeJS Application

Introduction

I've decided to start the practice of documenting issues, which is why I'm writing this blog post.

The technologies used in this project include NodeJS, MongoDB, ES6, Express, HTML5, CSS3, and Pug.

While previewing the YouTube clone coding (nomadcoders), a problem arose where user information was not reflected when redirected to the root page after social login. Through this, I learned that asynchronous processing is required because it takes time to save the session after social login.

Description of the Issue

  1. After social login, when redirected to the root page, the logged-in user information should be reflected and shown on the screen like this:

    Image description

  2. However, although a cookie containing user information was created, the page was rendered without reflecting any information, just like the pre-login page.

    Image description

  3. Only after refreshing the page did the user's login information reflect, as shown in the first screenshot.

Problem Analysis

  1. The first feedback I received was that a session cookie should be received even when not logged in. However, according to the saveUninitialized: false setting of express-session, the current code does not initialize cookies when not logged in, so both the browser and server did not separately save the cookies. (Information about the session does exist.)

    // server.js
    // ...
    app.use(
      session({
        secret: process.env.COOKIE_SECRET,
        resave: false,
        saveUninitialized: false, // this option
        store: MongoStore.create({ mongoUrl: process.env.DB_URL }),
      }),
    );
    // ...
    

    Image description

    saveUninitialized

    Forces a session that is “uninitialized” to be saved to the store. A session is uninitialized when it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with race conditions where a client makes multiple parallel requests without a session.

    The default value is true, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case.

    Note if you are using Session in conjunction with PassportJS, Passport will add an empty Passport object to the session for use after a user is authenticated, which will be treated as a modification to the session, causing it to be saved. This has been fixed in PassportJS 0.3.0

  2. Nico gave feedback that the redirection might occur before the session information is saved. He said that you need to wait for the session information to be saved because it takes time. After social login, there is a cookie containing user information, but it seems this is the cause because it was not reflected in the rendering page.

Solution

To solve this problem, I modified the code according to Nico's feedback. In the finishGithubLogin function, I used await req.session.save() to save the session information and then redirected it as follows:

// userController.js
// ...
let user = await User.findOne({ email: emailObj.email });
if (!user) {
  user = await User.create({
    // ...
  });
}
req.session.loggedIn = true;
req.session.user = user;
await req.session.save(); // this part
return res.redirect('/');
// ...
Enter fullscreen mode Exit fullscreen mode

I was able to solve the problem by simply adding this one line of code.

Conclusion

The cause of the problem was that the redirection occurred before the session information was saved. To solve this, I modified the code to save the session information using await req.session.save() and then perform redirection. As a result, user information was correctly reflected and displayed on the page.

After Writing the Blog..

Even after modifying the code, the same problem often occurred. I sought advice from a member of Nomad Coders regarding this issue. He explained that, due to the stack, there is considerably little that can be handled internally by the client in the current code design. This is because, when using React or SPA libraries, the JS Engine ends up just waiting for responses to server requests to solve problems that it could resolve. Ultimately, it's a structural limitation.

If anyone has ideas about other possible causes, please share your advice with me. Thank you.

References

Top comments (0)