Passport.js & Express Session - req.user undefined causing .isAuthenticted() to return false

TomPlum

I've spent more time than I'd like to admit scouring countless posts online that have the same problem as me, to no avail. The majority of solutions seemed to be things like not including

  • passReqToCallback: true in my LocalStrategy.
  • passport.serializeUser() and passport.deserializeUser() in my init file.
  • app.use(passport.initialize()) and app.use(passport.session()) in app.js.
  • Requiring and using app.use(cookieParser()) in app.js.
  • Passing cookie parser my secret key.
  • Adding proxy and cookie attributes to my expressSession variable in app.js.
  • Invoking req.login inside passport.authenticate within my page route.
  • And several other little tweaks I can't remember...

My login.js is as follows;

var LocalStrategy = require('passport-local').Strategy;
var User = require('../../models/user');
var bCrypt = require('bcrypt-nodejs');

module.exports = function(passport) {
    passport.use('login', new LocalStrategy({passReqToCallback: true},
        function(req, username, password, done) {
            //Queries MongoDB For User
            User.findOne({'username':  username}, function(err, user) {
                //In The Event Of An Error, Throw It
                if (err) {
                    return done(err);
                }

                //Username Does Not Exist, Log Error, Callback, Flash Error Message
                if (!user){
                    console.log('User: '+ username + ", does not exist.");
                    return done(null, false, req.flash('message', 'User Not found.'));
                }

                //User Exists, But Password Is Incorrect
                if (!isValidPassword(user, password)){
                    console.log('Invalid Password');
                    return done(null, false, req.flash('message', 'Invalid Password')); // redirect back to login page
                }

                //If No Previous Error Conditions Are Met - Username/Password Are Correct
                console.log("Validated User: " + username + ".");
                //req.user = user;
                return done(null, user);
            }); //End of User.findOne()
        }) //End of new LocalStrategy
    ); //End of passport.use()

    /*
    var isValidPassword = function(user, password){
        return bCrypt.compareSync(password, user.password);
    }
    */

    //Passwords are not currently hashed in my DB, so ignore bcrypt for now.
    var isValidPassword = function(user, password) {
        return user.password == password;
    }
}

My passport-init.js file

var login = require('./login');
var User = require('../../models/user');

module.exports = function(passport){
    //Serialise User
    passport.serializeUser(function(user, done) {
        console.log("Serializing User: " + user.username + "\n" + user + ".");
        done(null, user._id);
    });

    //De-Serialise User
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            console.log("Deserializing User: " + user.username + "\n" + user);
            done(err, user);
        });
    });

    //Setting up Passport Strategy for Login
    login(passport);
}

My index.js file contains the POST Login route

/* POST Login Page*/
router.post('/login', passport.authenticate('login', {
    successRedirect: '/dashboard',
    failureRedirect: '/login',
    failureFlash: true
}));

And dashboard.js contains all the routing for /dashboard/other-pages. These ones are protected by the isAuthenticated function.

var express = require('express');
var router = express.Router();
var database = require('../public/javascripts/db-connect.js');

var isAuthenticated = function(req, res, next) {
    console.log("User: " + req.user);
    console.log("Authenticated?: " + req.isAuthenticated());
    if (req.isAuthenticated()) {
        return next();
    } else {
        res.redirect('/unauthorised');
    }
}

module.exports = function(passport) {
    //Routes /dashboard --> dashboard.pug
    router.get('/', isAuthenticated, function(req, res, next) {
        database.getData("busdata", function(err, data) {
            if (err) {
                console.error(err);
            } else {
                res.render('dashboard', {title: 'Dashboard', busdata: data});
            }
        });
    });

    //Routes /dashboard/journeys --> journeys.pug
    router.get('/journeys', isAuthenticated, function(req, res, next) {
        database.getData("journeydata", function(err, data) {
            if (err) {
                console.error(err);
            } else {
                res.render('journeys', {title: 'Journey Graphs', journeydata: data});
            }
        });
    });

    return router;
}

So when I run the app;

  • I check localhost:3000/dashboard and localhost:3000/dashboard/journeys. They correctly re-direct me to /unauthorised.
  • Navigate to /login.
  • Enter a correct username and password, the console then spits out:
  • Validated User: TomPlum. Meaning passport.use() reached return done(null, user)
  • Serialising User: TomPlum + the objects properties
  • POST /login 302 time ms
  • User: undefined from isAuthenticated
  • isAuthenticated? false
  • GET /dashboard 302 time ms
  • Deserialising User: TomPlum + the objects properties
  • I'm then redirected to /unauthorised as isAuthenticated() evaluates to false.

Why is req.user undefined? Should I be using a LocalStrategy if my MongoDB is not-local? (Amazon Atlas Server). Other forum posts have suggested it could be a cookie issue but I've included the relevant cookie-parser includes in my app.js file.

app.js is here in-case it's an order issue.

//Require Variables
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

//Mongo DB Connection Settings
var dbConfig = require('./db'); //db.js contains DB URL
var mongoose = require('mongoose');
mongoose.connect(dbConfig.url); //dbConfig.url refers to the export in db.js

//Page Routing
//var index = require('./routes');
var users = require('./routes/users');
var dashboard = require('./routes/dashboard')(passport);

var app = express();
app.d3 = require('d3');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public/images', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('urban_sensing'));
app.use(express.static(path.join(__dirname, 'public')));

//app.use('/', index);
app.use('/dashboard', dashboard);
app.use('/users', users);

//Configuring Passport
var passport = require('passport');
var expressSession = require('express-session');
app.enable('trust-proxy');
app.use(expressSession({
    secret: 'urban_sensing',
    resave: true,
    saveUninitialized: true,
    proxy: true,
    cookie: {
        secure: true,
        maxAge: 3600000
    }
}));
app.use(passport.initialize());
app.use(passport.session());

//Flash Messaging For Passport
var flash = require('connect-flash');
app.use(flash());

//Initialize Passport

var initPassport = require('./public/javascripts/passport-init');
initPassport(passport);

var index = require('./routes/index')(passport);
app.use('/', index);

//Catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

//Error Handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

Some of the app.use(expressSession({..})); properties may currently be unnecessary as they've been added in an attempt to fix the issue.

Any help would be appreciated.

TomPlum

After too much time on this, turns out it was simply the order of app.js.

By moving

var dashboard = require('./routes/dashboard')(passport);

app.use('/dashboard', dashboard);

below all the passport configuration. It now works correctly. It seems that something wasn't initialised correctly during the routing of /dashboard when it was before the passport code.

Updated app.js

//Require Variables
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

//Mongo DB Connection Settings
var dbConfig = require('./db'); //db.js contains DB URL
var mongoose = require('mongoose');
mongoose.connect(dbConfig.url); //dbConfig.url refers to the export in db.js

//Page Routing
//var index = require('./routes');
var users = require('./routes/users');


var app = express();
app.d3 = require('d3');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public/images', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('urban_sensing'));
app.use(express.static(path.join(__dirname, 'public')));

//app.use('/', index);

app.use('/users', users);

//Configuring Passport
var passport = require('passport');
var expressSession = require('express-session');
app.use(expressSession({
    secret: 'urban_sensing',
    resave: false,
    saveUninitialized: true,
    cookie: {
        maxAge: 3600000 //1 Hour
    }
}));
app.use(passport.initialize());
app.use(passport.session());

//Flash Messaging For Passport
var flash = require('connect-flash');
app.use(flash());

//Initialize Passport
var initPassport = require('./public/javascripts/passport-init');
initPassport(passport);

var dashboard = require('./routes/dashboard')(passport);
app.use('/dashboard', dashboard);

var index = require('./routes/index')(passport);
app.use('/', index);

//Catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

//Error Handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

passport.js req.user is returning: 'Promise { false }' - How do I get the current sessions' username?

Express.js req.body undefined

req.session.passport and req.user blank , and req.isAuthenticated returns false after initial successful login using passport-facebook

Express Passport.js: req.user VERSUS req.session.passport.user

Unable to access req.user with Passport.js and Express 4

req.session.passport and req.user empty, serializeUser and deserializeUser are never called

req.session is undefined using express-session

NodeJS Express req[user] undefined on multiple refresh

GraphQl and passport session: access req.user when querying GraphQl

Node + Express + Passport + Mongoose: req.user Undefined

Express + Passport.js: req.user is UNDEFINED

req.user is undefined node + express + passport + mongoose

Passport req.user is undefined when using GitHub strategy

Passport + Express + Typescript req.user.email undefined

Lazy loading req.user, with express and passport?

Passport.js, Sessions, & React | Accessing req.user from any route other than the /login route is undefined

Node js passport's req.isAuthenticated returns always false

Express-session + Passport + MongoDB - req.isAuthenticated() always return false after login

req.session undefined in Express.js

express:- altering req.session of another user

Passport.js - passing {user: req.user} to template implicitly?

req.user undefined in Express 4

Express + Passport: req.user resets on every code save

Session of logged user return undefined

Express Passport.js not persisting user object in session

typescript: req.user is possibly 'undefined' - express and passport js

When using passport.js and ngrok, req.user is undefined because of cors

req.user if undefined in guards whileusing nest js + jwt + passport

Req.user is undefined and passport.deserializeUser is never been called in express app