PassportJS(Local) with Sequelize and Express stuck

2019-06-02 07:30发布

问题:

I'm trying to make login work, using the tutorial I've found in http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619. I modified the code to work with Sequelize. I was able to verify username and password, but after serializing a user, the page that it redirects to does not load. I was wondering if there's something I missed.

I'm not really getting an error, but redirecting to /test/home page is stuck on pending, and it keeps executing a post request. It doesn't seem to run req.isAuthenticated() either

Executing (default): SELECT "id", "email", "username", "password" FROM "users" AS "user" WHERE "user"."username" = 'user14' LIMIT 1;
username and password matched
serializing user: 
POST /test/login 302 377.738 ms - 64
Executing (default): SELECT "id", "email", "username", "password" FROM "users" AS "user" WHERE "user"."id" = 16;
GET /test/home - - ms - -
Executing (default): SELECT "id", "email", "username", "password" FROM "users" AS "user" WHERE "user"."id" = 16;
POST /test/home - - ms - -
Executing (default): SELECT "id", "email", "username", "password" FROM "users" AS "user" WHERE "user"."id" = 16;
POST /test/home - - ms - -

Here's a snippet of my app.js:

// configuring passport
var passport = require('passport');
var expressSession = require('express-session');
app.use(expressSession({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());

// initialize passport
var initPassport = require('./passport/init');
initPassport(passport);

// routes
var routes = require('./routes/index');
var loginTest = require('./routes/test')(passport);
var gameRoute = require('./routes/game');
app.use('/', routes);
app.use('/test', loginTest);
app.use('/game', gameRoute);

init.js:

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

module.exports = function(passport){
    passport.serializeUser(function(user, done) {
        console.log('serializing user: ');
        done(null, user.get('id'));
    });

    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            console.log('deserializing user:',user);
            done(err, user);
        });
    });

    // setting up Passport Strategies for Login
    login(passport);

}

test.js (router)

var express = require('express');
var router = express.Router();

var isAuthenticated = function (req, res, next) {
    if (req.isAuthenticated())
        return next();
    res.redirect('/test');
}

module.exports = function(passport){

    router.post('/login', passport.authenticate('login', {
        successRedirect: '/test/home',
        failureRedirect: '/test',
        failureFlash : true  
    }));


    /* GET Home Page */
    router.get('/home', isAuthenticated, function(req, res){
        res.render('home', { user: req.user });
    });

    return router;
}

login.js

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

module.exports = function(passport){

    passport.use('login', new LocalStrategy({
          passReqToCallback : true
      },
      function(req, username, password, done) { 
        // check if user with username exists or not
        User.findOne({ 
          where: {
            username:  username 
          }
        }).then(function(user) {
            if (!user){
              console.log('User Not Found with username '+username);
              return done(null, false, { message: 'Incorrect username.' });       
            }
            if (!isValidPassword(user, password)){
              console.log('Invalid Password');
              return done(null, false, { message: 'Incorrect password.' });
            }
            console.log('username and password matched');
            return done(null, user);
          }
        );

      })
  );

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

}

回答1:

After some research, I realised that what was causing the problem was deserializing. My console.log was not giving me an error, because it's stuck at User.findById(...). Sequelize doesn't return a callback, but a promise instead.

Instead of using this for init.js,

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    console.log('deserializing user:',user);
    done(err, user);
  });
});

Use this syntax instead

passport.deserializeUser(function(id, done) {
  User.findById(id).then(function(user) {
    console.log('deserializing user:',user);
    done(null, user);
  }).catch(function(err) {
    if (err) {
      throw err;
    }
 });
});