Search code examples
node.jsexpressauthenticationpassport.jsexpress-4

ExpressJS: Can't login using passport.js


This is my first time using passport in an expressJS project.

I'm facing an issue though. When i'm trying to login, i'm submitting my data and the app always fails to authenticate.

My app.js file includes these, that are related to passport:

// Passport Config
require('./config/passport')(passport);

// Login
app.post('/users/login', (req, res, next) => {
   passport.authenticate('local', {
         successRedirect: '/dashboard',
         failureRedirect: '/users/login',
         failureFlash: false
   })(req, res, next);
});

// Passport middleware
app.use(passport.initialize());
app.use(passport.session());

// Express body parser
app.use(express.urlencoded({ extended: false }));

I also have a passport.js file which is inside the config directory (/config/passport.js)

Inside this file, i've created my LocalStrategy, which is responsible for the success or the failure of the login authentication.

Inside the passport.js file i have:

const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";`

module.exports = function(passport) {
    console.log('check if printing-- it is printing')
    passport.use(
        new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
            console.log('check if printing-- it is not printing')
            // Match user
            MongoClient.connect(url, function(err, db) {
                var dbo = db.db("chat_db");
                dbo.collection('users').findOne({
                email: email
                }).then(user => {
                    if (!user) {
                        console.log('That email is not registered');
                    //   return done(null, false, { message: 'That email is not registered' });
                }

                // Match password
                bcrypt.compare(password, user.password, (err, isMatch) => {
                    if (err) throw err;
                    if (isMatch) {
                        return done(null, user);
                    } else {
                        return done(null, false, { message: 'Password incorrect' });
                    }
                });
                });
            })
        })
    );

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

   passport.deserializeUser(function(id, done) {
      MongoClient.connect(url, function(err, db) {
        var dbo = db.db("chat_db");
        dbo.collection('users').findById(id, function(err, user) {
            done(err, user);
        });
      });
   })
};

I believe that the issue exists inside the passport.use(...) part of the code, but i can't figure it out. I've placed two console.log() test inside the code, in order to check which methods are called or not. I've also tested the dbo.collection('users').findOne() part, which does find the data with the provided email, so i suppose there's no problem with that.

Can anyone help me with this? I don't know why the passport.use(...) is not being called and so the login always fails and always redirects me to the login page, instead of the dashboard. Your help will be much appreciated, thank you for your time.


Solution

  • You are loading your passport/body parser middlewares after your route, so they will never get called for your login route. They need to be defined first. Also it appears you are defining your route differently than the documentation suggests, and can be simplified as such:

    // Passport Config
    require('./config/passport')(passport);
    
    // Passport middleware
    app.use(passport.initialize());
    app.use(passport.session());
    
    // Express body parser
    app.use(express.urlencoded({ extended: false }));
    
    // Login
    app.post('/users/login',
      passport.authenticate('local', {
        successRedirect: '/dashboard',
        failureRedirect: '/users/login',
        failureFlash: false
      })
    );