Node + Express + Passport: req.user Undefined

My question is similar to this one, but there was no insight into his solution.

I'm using Passport to auth using Instagram. After successful auth, users are directed to "/". At this point, the request has the user object (aka it's working). However, once I redirect, the req.user is undefined. :'(

The odd part is that passport.deserializeUser is being called with each request. It's successfully getting the user object, but somewhere along the middleware road, req.user is not being set (or being unset).

// on successful auth, goto "/" 
app.get('/', function(req, res) {
    // if the request has the user object, go to the user page
    if (req.user) {
        res.redirect("/user/" + req.user._id);
    }

    res.render("index");
}

app.get('/user/:uid', function(req, res) {
    console.log(req.user) // undefined
}

Have you set up session state for your app? You need something like this...

app.use(session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());

I am super new to Node but it was a middleware issue for me. Added bodyParser and rearranged to fix.

Broken code:

app.use(express.cookieParser('secret'));
app.use(express.cookieSession());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public'))); 

Working Code:

app.use(express.static(path.join(__dirname, 'public')));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);

Hope this helps

Yeah enable sessions like @Martin says. But if you are using Express 4.* version, middleware like sessions are not bundled so you need to install it individually.

  1. Add "express-session": "1.4.0" in your package.json
  2. npm install
  3. use it

    var express = require('express') var cookieParser = require('cookie-parser') var session = require('express-session')

    var app = express()

    app.use(cookieParser()) // required before session. app.use(session({secret: 'keyboard cat'}))

For more information check the express session documentation.

In routes, try adding: {session: true}

app.get('/auto-login', passport.authenticate('cross', {session: true}))

I had this exact same problem using express 4 and after trying pretty much everything I could find online I finally managed to get it working by adding 'cookie-session'.

var cookieSession = require('cookie-session');

app.use(cookieSession({
  keys: ['key1', 'key2']
}));

If your middleware stack is unclear, assuming you have session middleware somewhere, you can save the session before the redirect:

if (req.user) {
    req.session.save(function (err) {
        if (err) {
            // ... panic!
        }
        res.redirect("/user/" + req.user._id);
    });
    return;
}

Have you tried to insert in the cookieParser your secretKey?

var passport = require('passport');
var expressSession = require('express-session');

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('mySecretKey'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressSession({
secret: 'mySecretKey',
  resave: false,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

This is old, but for future reference: you need to change the path variable in the express-session settings. the default is "/" which is the problem, you want for all paths:

app.use(expressSession({
    secret: '123456',
    resave: false, 
    saveUninitialized: false, 
    path:"/*" //NEEDED

}));

Modify the path variable if you want only for certain paths of course.

EDIT: This might be wrong, it solved my problem but only for 10 minutes then it was broken again. not sure whats going on.