Node + Express + Passport: req.user Undefined

node.jsExpresspassport.js

node.js Problem Overview


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
}

node.js Solutions


Solution 1 - node.js

My issue was not specifying to send cookies when using fetch on the client-side. It worked after including the credentials: 'include' field in the request.

fetch('/api/foo', {credentials: 'include'})

Solution 2 - node.js

Have you set up session state for your app? If you haven't, you need something like this...

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

Solution 3 - node.js

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

Solution 4 - node.js

Previously I have these code (did not work):

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
	secret: 'abcdefg',
    resave: true,
 	saveUninitialized: false,
    cookie: { secure: true } // this line
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

Then I remove the cookie option from session initializer:

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

and now it works.

Solution 5 - node.js

I encounter the same problem because of just copy & paste following code from express-session documentation, but not fully read the documentation.

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

In the documentation, it mentioned:

> However, it requires an https-enabled website, i.e., HTTPS is > necessary for secure cookies. If secure is set, and you access your > site over HTTP, the cookie will not be set.

so if you just have a HTTP connection, remove the secure option,and below code should work:

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  //cookie: { secure: true } remove this line for HTTP connection
}))

Solution 6 - node.js

I think everyone has several mistakes on server-side which can cause this problem.

To solve this error, please check these things:

Check 1 - Passport Serialization and Deserialization

The correct way to do it (Mongoose):

passport.serializeUser((user, done) => {
    done(null, user._id);
});

passport.deserializeUser((_id, done) => {
  User.findById( _id, (err, user) => {
    if(err){
        done(null, false, {error:err});
    } else {
        done(null, user);
    }
  });
});
Check 2 - Sessions

Check your cookie-session package is configured properly and working. Check if you can actually see cookie on client-side. If you are using express-session please make sure you can see session-id in memory or cache(Redis).

Check 3 - SSL nginx

Make sure your reverse proxy supports cookies and request type. Don't forget to check cookie/session configuration [secure flag]

When I face this error, I was using (user) for callback function. Then I corrected it with (err, user). Now its all right. Cheers 

Solution 7 - node.js

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.

Solution 8 - node.js

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']
}));

Solution 9 - node.js

In routes, try adding: {session: true}

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

Solution 10 - node.js

When you authenticate a user, the request value req.user is filled. To know if the identify the user and fill that value, a cookie is used. If like me, you configure the session with secure cookies, cookies will be available only over HTTPS, which is not the standard configuration for, let's say, a local development server. To have cookies work over HTTP, comment out cookie: { secure: true } and req.user value will be properly configured:

this.app.use(session({
    resave: true,
    saveUninitialized: true,
    secret: process.env.SESSION_SECRET || "a secret",
    // cookie: { secure: true },
}));

If, reasonably, you want cookies over HTTPS only in production, you can do something like:

cookie: { secure: process.env.ENV === 'PRODUCTION' }

Solution 11 - node.js

While doing passport.authenticate you can add session: true to resolve your issue:

app.post("/login", passport.authenticate('local', {
	'failureRedirect': '/login',
	'session': true
}), (req, res)=>{ res.redirect("/"); });

Solution 12 - node.js

'req.user' was being set to the user for me only after passport.auth middleware. I came to this thread trying to find out how to access the username from other requests (without passport.auth middleware), if anyone else is stuck on that issue then try

req._passport.session.user;

Solution 13 - node.js

Mine was about cookies & cors. I solved by adding following code to my server:

allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // your website
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if ('OPTIONS' === req.method) {
    res.send(200);
} else {
    next();
}};

Solution 14 - node.js

Once you have your express session setup make sure you have passport serialize & deserialize, in the deserialize function that's when req.user gets generated. See explanation here from another stackoverflow question.

passport.serializeUser(function(user, done) {
 done(null, user);
});


passport.deserializeUser(function(user, done) {
 done(null, user);
});

Solution 15 - node.js

When u use http request on client side, remember to attach credentials. In Angular2 you need to add option argument: { withCredentials: true }. After this you will have the same req.sessionID until you reset it again.

this._http.get("endpoint/something", { withCredentials: true })

Solution 16 - node.js

Mine was different from all these. I had been previously developing on localhost a Wordpress site and then switched to a separate Node/React project.

The cookie from the Wordpress site was still present and being sent since both projects ran on localhost. This was causing the issue.

I had to clear the cookies for localhost and then it worked.

Solution 17 - node.js

Server sends SetCookie header then the browser handle to store it, and then the cookie is sent with requests made to the same server inside a Cookie HTTP header.

I had to set withCredentials: true in my client. (axios.js)

const config = {
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
  },
};

axios.put(url, { page: '123' }, config)
  .then(res => console.log('axios', res))
  .catch(err => console.log('axios', err));

Then CORS problems occur.

So I added this to my express server:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  if ('OPTIONS' == req.method) {
    res.send(200);
  } else {
      next();
  }
});

Solution 18 - node.js

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;
}

Solution 19 - node.js

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());

Solution 20 - node.js

Had exactly the same problem. For me, the solution was to use "client-sessions" instead of 'express-session". Probably bad sessions configuration?

Not working code:

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

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(session({
    secret: 'random string',
    resave: true,
    saveUninitialized: true,
    cookie: { secure: true }
}));

Working code:

var session = require('client-sessions');

        app.use(bodyParser.urlencoded({ extended: false }));
        app.use(express.static(path.join(__dirname, 'public')));
        app.use(cookieParser());
        app.use(bodyParser.json());
        app.use(session({
        cookieName: 'session',
        secret: 'random string',
        duration: 30 * 60 * 1000,
        activeDuration: 5 * 60 * 1000,
    }));

Solution 21 - node.js

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();
})

See, if you are accessing req.user after passport.session(), if not add your route below.

Solution 22 - node.js

My two cents: not working code:

server.use(
session({
  secret: "secretsssss",
  rolling: false,
  resave: false,
  saveUninitialized: false,
  cookie: {
    sameSite: true, //this line
    maxAge: 60 * 60 * 1000
  }
})
);

working code:

server.use(
session({
  secret: "secretsssss",
  rolling: false,
  resave: false,
  saveUninitialized: false,
  cookie: {
    sameSite: false, // i think this is default to false
    maxAge: 60 * 60 * 1000
  }
})
);

Solution 23 - node.js

Ran into this same problem, however mine was more related to a misunderstanding of the difference between passport.authorize and passport.authenticate in the start of the OAuth flow and OAuth callback routes.

passport.authorize won't affect the req.user variable, but since I just copy-pasta'd the sample code from the strategy's docs, I didn't realize the wrong method was being used. After changing to passport.authenticate the user variable was available.

Hope this helps anyone who may be unknowingly doing the same thing.

Solution 24 - node.js

Change the order from this:

app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));

to this:

app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");

Solution 25 - node.js

I was using cookie-parser along with express-session like this:

var express = require("express"); // 4.16.1
var cors = require("cors"); // 2.8.5
var cookieParser = require("cookie-parser"); // 1.4.4
var expressSession = require("express-session"); // 1.17.1

var app = express();

app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
);

app.use(express.json());
app.use(express.urlencoded({ extended: true }));


app.use(
  expressSession({
    secret: "secret123",
    resave: true,
    saveUninitialized: true,
    cookie: { maxAge: 60 * 60 * 24 * 1000 },
  })
);
app.use(cookieParser("secret123")); // this line

Putting cookie-parser before express-session worked for me, like this:

var express = require("express"); // 4.16.1
var cors = require("cors"); // 2.8.5
var cookieParser = require("cookie-parser"); // 1.4.4
var expressSession = require("express-session"); // 1.17.1

var app = express();

app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
);

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(cookieParser("secret123"));
app.use(
  expressSession({
    secret: "secret123",
    resave: true,
    saveUninitialized: true,
    cookie: { maxAge: 60 * 60 * 24 * 1000 },
  })
);

Solution 26 - node.js

I had a different issue, something with bcrpt-node and arrow functions.

Code that works:

userSchema.methods.generateHash = function (password) {
  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); 
};

userSchema.methods.isValidPassword = function (password) {
  return bcrypt.compareSync(password, this.password);
};

Code that does not work:

userSchema.methods.generateHash = (password) => {
  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

userSchema.methods.isValidPassword = (password) => {
  return bcrypt.compareSync(password, this.password);
};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongojohnnygoView Question on Stackoverflow
Solution 1 - node.jsJon RodnessView Answer on Stackoverflow
Solution 2 - node.jsMartinView Answer on Stackoverflow
Solution 3 - node.jsleylandjacobView Answer on Stackoverflow
Solution 4 - node.jssanusiView Answer on Stackoverflow
Solution 5 - node.jsufxmengView Answer on Stackoverflow
Solution 6 - node.jsSmit PatelView Answer on Stackoverflow
Solution 7 - node.jsAdrian EnriquezView Answer on Stackoverflow
Solution 8 - node.jsergustoView Answer on Stackoverflow
Solution 9 - node.jsStrawberryView Answer on Stackoverflow
Solution 10 - node.jsAlain1405View Answer on Stackoverflow
Solution 11 - node.jsMaheshView Answer on Stackoverflow
Solution 12 - node.jsmrjackmcleanView Answer on Stackoverflow
Solution 13 - node.jsMohamedView Answer on Stackoverflow
Solution 14 - node.jsAric SangchatView Answer on Stackoverflow
Solution 15 - node.jsHonzikView Answer on Stackoverflow
Solution 16 - node.jsBreakpoint25View Answer on Stackoverflow
Solution 17 - node.jsSunny SultanView Answer on Stackoverflow
Solution 18 - node.jsexclsrView Answer on Stackoverflow
Solution 19 - node.jsMarco MantovaniView Answer on Stackoverflow
Solution 20 - node.jsLuisView Answer on Stackoverflow
Solution 21 - node.jsSyed Muhammad AsadView Answer on Stackoverflow
Solution 22 - node.jsRuizhen MaiView Answer on Stackoverflow
Solution 23 - node.jsjcarusoView Answer on Stackoverflow
Solution 24 - node.jsAlperView Answer on Stackoverflow
Solution 25 - node.jsAyan AdhyaView Answer on Stackoverflow
Solution 26 - node.jsMichaelView Answer on Stackoverflow