node-connect-pg-simple: Session not set immediately after login

I’m using this library with express-session, passport, and the Passport Google OAuth2.0 lib. When the user approves of logging in and gets redirected, req.user is not set (nor, say, req.session.passport.user). I send this info over to the client, so that they know who is logged in. Because it isn’t sent, the client believes that the user has not logged in, and redirects them back to the login page. If the user then refreshes that page, things are set at that time, and they are considered logged in.

The cookie is set, but the presence of the cookie isn’t very reliable. For instance, when they’re logged out, the cookie currently sticks around.

I set this app by following this example, using the in-memory session. The user was set immediately on being redirected. When I refactored to add in this lib, it no longer worked the same way.

Is this an issue anyone else has run into before? I’ve tried switching around the resave and saveUnitialized options to see if those would affect this, but with no luck.

The code is pretty awful – I’m trying to get it to work before refactoring – but you can see the configuration here.

Results of the investigation:

  • It’s also lagging behind when the user gets logged out. After hitting the /logout endpoint, they’re sent the user info until they refresh. Update: calling req.session.destroy explicitly fixed this. Full code at the end of this post.
  • Switching to pg rather than pg-promise did not solve the issue
  • Switching from multiple to a single process didn’t fix it either
Logout code

Simply calling req.logout() wasn’t working. Explicitly calling req.session.destroy(), on the other hand, forces the session to be destroyed 100% of the time.

app.get('/logout', (req, res) => {
  req.logout();
  req.session.destroy(function (err) {
    res.redirect('/login');
  });
});

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 22 (2 by maintainers)

Most upvoted comments

For me, the issue turned out that Chrome doesn’t wait for the whole response before redirecting. So express-session’s attempt to save to the DB wasn’t completed before the new request began. You can force it to wait by delaying the call to the redirect until you’re sure that the session is saved. In my app, this looked like:

app.get('/auth/google/callback', passport.authenticate('google', redirects),
  function(req, res) {
    // Explicitly save the session before redirecting!
    req.session.save(() => {
      res.redirect('/success');
    })
  });

Will send example tomorrow.

On Monday, July 4, 2016, James, please notifications@github.com wrote:

@jdposthuma https://github.com/jdposthuma just tried that – didn’t work for me. I placed it between app.use(session({ … })) and app.use(passport.initialize(). Do you have an example app anywhere showing how you’ve configured it?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/voxpelli/node-connect-pg-simple/issues/31#issuecomment-230357314, or mute the thread https://github.com/notifications/unsubscribe/AOfspAtIiut9nDtVyxxH4HrQHRf59cyoks5qSX89gaJpZM4ISiZ1 .

Jason Posthuma Developer 303-210-4525

@jmeas Any progress with this?

i had similar problems. the in memory store was working fine, but when i switched to this library, i also got timing problems

In my case i had

app.post('/login', passport.authenticate('login', { failureRedirect: '/login' }),
  function(req, res, next) {
      process.nextTick(function() {
          res.redirect('/');
      });
  });

the problem was: the post /login authenticated with and got a sessionId, but the redirect after the authentication caused a new request with a new sessionId (which was not authenticated)

changing res.redirct(“/”), to res.sendFile(__dirname + ‘/index.html’); solved my problem

Updates on the bug: I’ve been stepping through Passport, trying to make sense of it. Issue here:

https://github.com/jaredhanson/passport/issues/482

I also opened a SO question:

http://stackoverflow.com/questions/36975133/passport-js-isauthenticated-inconsistent-behavior-false-when-it-should-be-t

I still have reason to believe this is related to my pg config, because going back to the memory store makes everything work as expected (other than, you know, persisting across app reboots and so on).


Latest updates:

I’ve learned that the data is set up through the express-passport library. In cases where logging in fails, the createSession method does not receive the correct sess value.

The value of sess is what is returned by store.get(); therefore, this library must be returning the wrong thing from the DB on store.get().


even more updates.

  1. I cleared the session DB, to make sure that there were no sessions.
  2. I logged in, creating YOZHpILNhQZLnViw7-xrQ4D9hJpwfp_k in the db.
  3. The session middleware failed to find this session in the DB at the time that .get (from this library) was called!
  4. therefore, the session data was never set and the user appeared offline

It’s almost like it’s calling .get before it sets the value…which is whack!

Logs:

11:23:16 PM web.1 | -----New request /auth/google/callback 11:23:17 PM web.1 | logging in! 11:23:17 PM web.1 | serializing 11:23:17 PM web.1 | pgSimple: setting F7USqyUR-Ew-0huz06hZUhyGNJ1K9iTX 11:23:17 PM web.1 | fetching session F7USqyUR-Ew-0huz06hZUhyGNJ1K9iTX 11:23:17 PM web.1 | pgSimple: getting F7USqyUR-Ew-0huz06hZUhyGNJ1K9iTX 11:23:17 PM web.1 | no session found 11:23:17 PM web.1 | -----New request /success 11:23:17 PM web.1 | authenticated: false

…more to come


So…this seems to be a race condition in this lib or in express-session. The query to create a session in the DB is running after express-session tries to get the data.

Heh, yeah, I didn’t expect it to. I was just trying to verify that none of the differences in my own code was responsible for the bugs, however small they may be 😃


Updates on the bug:

I’m wondering if these bugs are due to using the profile returned from the service directly, rather than using a user account table in my DB. I was trying to get a halfway version working before adding user accounts, but atm I’m going forward with adding those to see if that fixes it.

Still investigating.

  • It’s also lagging behind when the user gets logged out. After hitting the /logout endpoint, they’re sent the user info until they refresh.
  • Switching to pg rather than pg-promise did not solve the issue
  • Switching from multiple to a single process didn’t fix it either