passport: req.user is undefined, passport not working with Express 4.0

I use passport@0.2.0 and passport-local@1.0.0.

req.user is alway undefined and so req.isAuthenticated() also not working.

Here is my express-setup:

var env = process.env.NODE_ENV || 'development';

var path = require('path'),
    expressValidator = require('express-validator'),
    config = require('../config/config')[env],
    RedisStore = require('socket.io/lib/stores/redis'),
    redis  = require('socket.io/node_modules/redis'),
    pub    = redis.createClient(),
    sub    = redis.createClient(),
    client = redis.createClient(),
    utils = require('connect').utils,
    cookieParser = require('cookie-parser');
    bodyParser = require('body-parser'),
    expressSession = require('express-session'),
    compress = require('compression'),
    morgan = require('morgan'),
    errorHandler = require('errorhandler'),
    methodOverwrite = require('method-override');

module.exports = function (app, passport, express, io) {
  var RedisSessionStore = require('connect-redis')(expressSession);
  var redisSessionStore = new RedisSessionStore(config.redis.sessions);

  app.use(morgan());
  app.use(cookieParser());
  app.use(methodOverwrite());
  app.use(bodyParser({ keepExtensions: true, uploadDir: config.files.upload.path, limit: config.files.upload.size }));
  app.use(expressValidator());
  app.use(expressSession({
    secret  : 'foo',
    cookie  : {
      expires: false,
      domain: config.cookie.domain
    },
    store: redisSessionStore
  }));

  app.use(passport.initialize());
  app.use(passport.session());

  // response static files
  if(env == 'development'){
    app.use(compress({
      threshhold: 512
    }));
    app.use('/', express.static(path.join(__dirname, '../../frontend')));
    app.use(errorHandler({ dumpExceptions: true, showStack: true }));
  }

  if(env == 'production'){
    app.use(errorHandler());
    app.enable('trust proxy');
  };
}

… and passport-setup:

var LocalStrategy = require('passport-local').Strategy,
    User = require('../model/User');

module.exports = function (passport) {
  // serialize sessions
  passport.serializeUser(function(user, done) {
    var sessionData = {};

    sessionData.user = user._id;

    // store workingAt to build socket.io rooms
    if(user.workingAt){
      sessionData.workingAt = user.workingAt;
    }

    done(null, sessionData);
  });

  // deserialize sessions
  passport.deserializeUser(function(sessionData, done) {
    User.findById(sessionData.user, function (error, user) {
      if(error){
        done(error);
      } else {
        done(null, user);
      }
    })
  });

  // use local strategy
  passport.use(new LocalStrategy({
        usernameField: 'email',
        passwordField: 'password'
      },
      function(email, password, done) {
        User.checkCredentials({email: email, password: password}, function(error, user){
          if(error) {
            return done(error);
          } else {
            return done(null, user);
          }
        });
      }
  ))

EDIT: I try to find the reason of that bug and its seems its related to express-session. On every request i have a new value in req.sessionID, also no cookie will be created with the sessionID.

About this issue

  • Original URL
  • State: open
  • Created 10 years ago
  • Reactions: 4
  • Comments: 30

Most upvoted comments

If you’re using the window.fetch method to send requests to your server, you have to include 'same-origin credentials in your request. See the example below.

fetch(url, { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, credentials: "same-origin" })

Watch out cookie property with ‘secure’ value if not in under https protocol req.user will be undefined.

Putting express.session() before passport.session() fixed the issue for me, thanks.

I had this problem. The fix was to add the express-session secret into the cookie parser. problem solved.

So the fix for above would be:

app.use(cookieParser(‘foo’)); app.use(expressSession({ secret : ‘foo’, cookie : { expires: false, domain: config.cookie.domain }, store: redisSessionStore }));

notice the cookie parser now contains the session secret.

It seems to me the real bug here isn’t that req.user can be undefined: the real problem is that many different things can all go wrong, and there’s no diagnostic info provided to the user whatsoever to help them figure out what they did wrong (which can be especially confusing because “they”, the server programmer, may not have done anything wrong, as the problem could be completely client-side).

It seems like at least the majority of the above cases could be caught. For instance, if passport sees two sessions for identical URLs except one has www. and one doesn’t, it seems like it would be trivial for it to console.warn("Multiple sessions for the same base URL detected (are you using credentials: 'same-origin'?)").

I would imagine these warnings would be very easy to implement, but they also sound like they’d be hugely valuable. After just losing half a day to the www. one specifically I’d certainly be willing to submit a PR for it, and possibly for others, if desired.

I had same issue, both with req.isAuthenticated() and req.user, here is how I resolved

  • req.isAuthenticated()

resolved by replacing findOne() with find() in findById() method inside deserialize(), then I could save authenticated req, else it was returning nothing.

  • req.user

resolved by adjusting order, first express-session should be stored then passport should be initialized then next session store in passport.session() and after that we can access req.user, after saving session in passport.session()

app.use(session(...))
app.use(passport.initialize());
app.use(passport.session());
// Now we can access req.user so after we will call req.user, if we write it above these, it will always return underfined
app.use(function(req, res, next){
  res.locals.user = req.user || null
  next();
})

Had isses with express-session. I switched to expressjs/cookie-session and seems to be working fine with express@4.42, passport@0.2.0, passport-persona

app.use(passport.initialize()); app.use(passport.session());

Thank you @asdkazmi !!!

Adding these below the express session use in app.js did the trick for me here in March 2024 😃

I, too, had this problem, and @SaydChada’s hint got me pointed in the right direction:

Watch out cookie property with ‘secure’ value if not in under https protocol req.user will be undefined.

Also note that if you do indeed want to request a secure cookie be sent to the browser (s/b typical, IMHO), but you’re using express-session and terminating TLS somewhere upstream, this little gem right there in the docs is a good answer:

If you have your node.js behind a proxy and are using secure: true, you need to set “trust proxy” in express

In my case, I’m running in Google App Engine, configured for TLS/SSL only, which terminates TLS upstream.

See also:

https://github.com/expressjs/session#cookiesecure https://expressjs.com/en/guide/behind-proxies.html https://github.com/expressjs/session/blob/master/index.js#L639

Guys, since you are using a custom callback to handle success/failures, it becomes the application’s responsibility to establish a session . So we need to set req.session.user = {…} in the strategies.

I added a new route to keep using “req.user”:

app.use((req, res, next) => {req.user = req.session.user; next()})

The issue for me was that I was not consistent in linking through my site. Make sure you either prefix ’ www.’ everywhere or nowhere, or a new session will be started for the two!