passport: passport is empty in session but has user in sessionStore

I’ve spent 4 hours scrolling through all SO posts about req.isAuthenticated() giving false always and then realizing that my session.passport lacks user itself and then figuring out that it appears in sessionStore once (I am using MemoryStore for now) and on second request it disappears, god knows why.

Please help me out.

import express from 'express';
import passport from 'passport';
import bodyParser from 'body-parser';
import constants from '../constants';
const app = express();

app.use('/', express.static(__dirname + '/../client'));

// Config
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json({ limit: '25mb' }));
app.use(require('express-session')({ 
  secret: 'yolo 123',
  resave: true,
  saveUninitialized: false,
  cookie: { maxAge : 24*60*60*1000 }, 
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(require('./passport-local'));

app.get('/test', (req, res) => { 
  console.log(req.sessionStore, req.sessionID, req.session);
  res.status(200).end(req.isAuthenticated() ? 'logged in': 'logged out');
});

app.post('/login', passport.authenticate('local'), (req, res) => {
  let user = req.user.toJSON();
  delete user.password;
  res.status(200).json({ user })
});
...

./passport-local.js

import { Strategy } from 'passport-local';
import constants from '../constants';
import passport from 'passport';
import { User } from './db';

passport.serializeUser((user, done) => done(null, user.id));

passport.deserializeUser((user, done) => (
  User.where({ id: user.id })
  .fetch()
  .then(u => done(null, u))
));

module.exports = new Strategy({ usernameField: 'username', passwordField: 'password' }, (username, password, done) => (
  User.where({ username }).fetch()
  .then(user => {
    if(user) {
      if (!password.compare(password, user.toJSON().password)) {
        return done(null, false, { message: 'Incorrect password.' });
      } else {
        return done(null, user);
      }
    } else {
      return done(null, false, { message: 'Incorrect username.' });
    }
  })
  .catch(console.log)

Flow: Login -> I receive user object with correct details from DB -> I visit /test

GET /test
MemoryStore {
  sessions: { N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX: '{"cookie":{"originalMaxAge":86400000,"expires":"2016-01-09T12:09:21.366Z","httpOnly":true,"path":"/"},"passport":{"user":"2"}}' },
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] },
  _eventsCount: 2 } 'N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX' Session {
  cookie: 
   { path: '/',
     _expires: Sat Jan 09 2016 17:39:21 GMT+0530 (IST),
     originalMaxAge: 86400000,
     httpOnly: true },
  passport: {} }

I revisit /test

GET /test
MemoryStore {
  sessions: { N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX: '{"cookie":{"originalMaxAge":86400000,"expires":"2016-01-09T12:09:24.179Z","httpOnly":true,"path":"/"},"passport":{}}' },
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] },
  _eventsCount: 2 } 'N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX' Session {
  cookie: 
   { path: '/',
     _expires: Sat Jan 09 2016 17:39:24 GMT+0530 (IST),
     originalMaxAge: 86400000,
     httpOnly: true },
  passport: {} }
  • Why is MemoryStore having {user:2} (that is the id) but not req.session on first request to /test
  • Why does it disappear in second request?

EDIT: Just used database (postgres) for session store, exact same behaviour. What piece of code is making an update entry on the passport: {} in session store and thus emptying it?

EDIT2: I’m adding/removing user to/from session myself in my login and logout routes for now, and they are persistent. I guess this has to do with passport getting confused or something like that.

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 3
  • Comments: 28

Commits related to this issue

Most upvoted comments

@MohammadHasham
undefined, In the above authcontroller.test If I’added line console.log(req.user)
its undefined Thank you

Me too. I feel like this is due to a race condition in the express session store, but I’m not sure. Very frustrating. Does anyone have even a dirty workaround?

I figured out what is the cause of this, using server.use( session({ cookie:blabla, resave: false, saveUninitialized: true, secret: process.env.RDS_COOKIE_SECRET, store: testEnvironment ? null : new require('connect-pg-simple')(session)() }) )

disable the store when you are sending so many login requests when testing some how causes a problem with using connect-pg-simple but now it is works just fine.

@kamalpreetgrewal I fixed it by enabling credential in headers when sending login request. It’s an issue about not using CORS.

Is it because of ES6 syntax? @MattMcFarland I think I’ve found the issue, I wasn’t using CORS.

Server Side:

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

Client Side:

  • If you are using fetch API then use following:
fetch('endpoint.json', {
  credentials: 'include',
...
  • If you are using jQuery/xhr then use withCredentials: true in the ajax object