PassportJS не распознает смену пароля

Я добавил некоторые функции сброса пароля к моему процессу регистрации, которые позволяют пользователям изменять свой пароль, но когда пользователь сбрасывает свой пароль, он не может войти в систему с новым паролем, и я получаю консольное сообщение Server Error. Мне интересно, связано ли это с обновлением пароля пользователя за пределами логики паспорта или, может быть, потому, что мой пароль не хэшируется при обновлении?

Вот лог консоли:

GET /login 200 9.507 ms - 1793
GET /stylesheets/styles.css 304 1.093 ms - -
Database query triggered
Executing (default): SELECT `user_id`, `first_name` AS `firstName`, `last_name` AS `lastName`, `email`, `password`, `organization_id` AS `organizationId`, `reset_password_token` AS `resetPasswordToken`, `reset_password_expires` AS `resetPasswordExpires`, `createdAt`, `updatedAt` FROM `user` AS `user` WHERE `user`.`email` = '[email protected]' LIMIT 1;
Server Error
POST /login 302 16.169 ms - 56
GET /login 200 10.926 ms - 1862

Вот мой маршрут обновления пароля:

var express = require('express');
var siteRoutes  = express.Router();
var path = require('path');
var async = require('async');
var crypto = require('crypto');
var nodemailer = require('nodemailer');
var sgTransport = require('nodemailer-sendgrid-transport');
var moment = require('moment');
var url = require('url');
var passport = require(path.resolve(__dirname, '..', '..','./config/passport.js'));
var models = require('../models/db-index');


    /*====   /RESET     ====*/

    siteRoutes.route('/reset/:token')

        .get(function(req, res){
            var urlPath = url.parse(req.url).pathname.split('/');
            var urlToken = urlPath[2];
            console.log(urlToken);
            models.User.findOne({
                where: {
                    resetPasswordToken: req.params.token,
                    resetPasswordExpires: {
                        $gt: moment().format('YYYY-MM-DD HH:mm:ss')
                    }
                }
            }).then(function(){
                res.render('pages/app/reset-password.hbs',{
                    urlToken: urlToken
                });
            })          
        })


        .post(function(req, res){
            async.waterfall([
                function(done){
                    models.User.update({
                        password: req.body.password,
                        resetPasswordToken: null,
                        resetPasswordExpires: null
                    }, { where: {
                        resetPasswordToken: req.body.token,
                        resetPasswordExpires: {
                            $gt: moment().format('YYYY-MM-DD HH:mm:ss')
                        }
                    }})
                // Nodemailer
                var transporter = nodemailer.createTransport(sgTransport(options));

                var mailOptions = {
                    from: '"Tester" <[email protected]',
                    to: '[email protected]', //Replace with Email
                    subject: 'Your password has been changed',
                    text: 'Hello,\n\n' +
              'This is a confirmation that the password for your account ' + '[email protected]' + ' has just been changed.\n'
                };

                transporter.sendMail(mailOptions, function(error, info){
                    if(error){
                        return console.log(error + 'During Post');
                    }
                    console.log('Message sent: ' + info.response);

                })
                }
            ])
            res.redirect('/login');
        });

Вот мой маршрут входа:

/*====  Login   ====*/


    siteRoutes.route('/login')

        .get(function(req, res){
            res.render('pages/site/login.hbs',{
                error: req.flash('error')
            });
        })

        .post(passport.authenticate('local', {
            successRedirect: '/app',
            failureRedirect: '/login',
            failureFlash: 'Invalid email or password.'
        }));

Вот модель пользователя:

var bcrypt   = require('bcrypt-nodejs');

module.exports = function(sequelize, DataTypes) {

var User = sequelize.define('user', {
    user_id: {
        type: DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true
    },
    firstName: {
        type: DataTypes.STRING,
        field: 'first_name'
    },
    lastName: {
        type: DataTypes.STRING,
        field: 'last_name'
    },
    email: {
        type: DataTypes.STRING,
        isEmail: true,
        unique: true,
        set: function(val) {
            this.setDataValue('email', val.toLowerCase());
        }
    },
    password: DataTypes.STRING,
    organizationId: {
        type: DataTypes.INTEGER,
        field: 'organization_id',
        allowNull: true
    },
    resetPasswordToken: {
        type: DataTypes.STRING,
        field: 'reset_password_token'
    },
    resetPasswordExpires: {
        type: DataTypes.DATE,
        field: 'reset_password_expires'
    }
}, {
    freezeTableName: true,
    classMethods: {
        associate: function(db) {
            User.belongsToMany(db.Organization, { through: 'member', foreignKey: 'organizationId'})
        },
        generateHash: function(password) {
            return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
        },
    },
    instanceMethods: {
        validPassword: function(password) {
            return bcrypt.compareSync(password, this.password);
        },
    },


});
    return User;
}

Вот логика паспорта:

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../app/models/db-index');

/*====  Passport Configuration  ====*/

// Serialize sessions
passport.serializeUser(function(user, done) {
    console.log("User ID: " + user.user_id + " is serializing");
  done(null, user.user_id);
});

passport.deserializeUser(function(user_id, done) {
  models.User.find({where: {user_id: user_id}}).then(function(user){
    console.log("User ID: " + user.user_id + " is deserializing");
    done(null, user);
  }).error(function(err){
    done(err, null);
  });
});

//Login logic
passport.use('local', new LocalStrategy({
    passReqToCallback: true,
    usernameField: 'email'
},  function(req, email, password, done) {
        console.log("Database query triggered");
        //Find user by email
        models.User.findOne({
            where: { 
            email: req.body.email
            }
        }).then(function(user) {
            if (!user) {
                done(null, false, { message: 'The email you entered is incorrect' }, console.log("Unknown User"));
            } else if (!user.validPassword(password)){
                done(null, false, console.log("Incorrect Password"));
            } else {
                console.log("User match");
                done(null, user);
            }
        }).catch(function(err) {
            console.log("Server Error");
            return done(null, false);
        });
    }));

//Sign Up Logic
passport.use('local-signup', new LocalStrategy({
    passReqToCallback: true,
    usernameField: 'email'
}, function(req, email, password, done){
    models.User.findOne({
        where: {
            email: email
        }
    }).then(function(existingUser){
        if (existingUser)
            return done(null, false, req.flash('error', 'Email already exists.'));
        if (req.user) {
            var user = req.user;
            user.firstName = firstName;
            user.lastName = lastName;
            user.email = email;
            user.password = models.User.generateHash(password);
            user.save().catch(function(err){
                throw err;
            }).then(function(){
                done(null, user, req.flash('error', 'All fields need to be filled in'));
            });
        } else {
            var newUser = models.User.build({
                firstName: req.body.firstName,
                lastName: req.body.lastName,
                email: req.body.email,
                password: models.User.generateHash(password)
            });

            newUser.save().then(function(){
                done(null, newUser);
            }).catch(function(err){
                done(null, false, console.log(err));
            });
        }
    }).catch(function(e){
        done(null, false, req.flash('error', 'All fields need to be filled in'),console.log(e.email + e.message));
    })
}));

module.exports = passport;

person cphill    schedule 04.04.2016    source источник
comment
Нет, это не связано с логикой паспорта, когда вы обновляете свой пароль пользователя, вам просто нужно снова сгенерировать хэш пароля (bcrypt). Внутренним компонентам паспорта не нужно знать об этом, шифрование/дешифрование, хеширование и аутентификация всегда обеспечиваются вашей логикой.   -  person Eduardo Pereira    schedule 04.04.2016


Ответы (1)


Похоже, вы снова забыли сгенерировать пароль.

.post(function(req, res){
  async.waterfall([
    function(done){
      models.User.update({
        password: models.User.generateHash(req.body.password)
person Eduardo Pereira    schedule 04.04.2016
comment
Это сработало. Благодарю вас! Можно ли предположить, что мой метод «local-signup» в файле паспорта выдавал ошибку, потому что для него установлено значение models.User.generateHash(password), поэтому он ищет хэшированное значение? - person cphill; 05.04.2016