使用 passport-local-mongoose 重置密码时遇到问题

Trouble with password reset with passport-local-mongoose

我想在我的网站上添加忘记密码功能。我想要典型的流程:我希望用户提交他们的电子邮件地址,收到一封带有重置 link 的电子邮件,输入一个新密码来替换他们当前的密码并登录。我几乎可以正常工作但我明白了更改密码后尝试登录用户时出错。

我错过了什么?

这是我遇到的错误:

error null
user false
info { AuthenticationError
    at /Users/Tom/Heroku/airbnb-toolkit/node_modules/passport-local-mongoose/lib/authenticate.js:50:36
    at /Users/Tom/Heroku/airbnb-toolkit/node_modules/mongoose/lib/model.js:3431:16
    at /Users/Tom/Heroku/airbnb-toolkit/node_modules/mongoose/lib/services/model/applyHooks.js:144:20
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickCallback (internal/process/next_tick.js:104:9)
  name: 'IncorrectPasswordError',
  message: 'signin.errors.incorrect-password' }

这是我的 node.js 代码:

app.post('/forgot', async function(req, res, next) {
    try {
        var buf = await crypto.randomBytes(20);
        var token = buf.toString('hex');
        var username = req.body.username;
        var user = await User.findOneAndUpdate(
            {username},
            {
                resetPasswordToken: token,
                resetPasswordExpires: moment().add(1, 'hour').toDate()
            }
        );
        if (!user) {
            handleError(res, 'No account with that email address exists.', 'No account with that email address exists.', 421);
        }
        sendEmail(username, "Superhost Tools Password Reset", "You are receiving this because you have requested the reset of the password for your account. Please click on the following link, or paste this into your browser to complete the process: http://example.com/#!/reset/" + token + "  If you did not request this, please ignore this email and your password will remain unchanged.");
        res.status(200).json("success");
    } catch(error) {
        console.error(error);
        handleError(res, error.message, "/forgot");
    }
});

app.post('/reset', async function(req, res, next) {
    try {
        var resetPasswordToken = req.body.resetPasswordToken;
        var username = req.body.username;
        var password = req.body.password;
        var user = await User.findOneAndUpdate({
            username,
            resetPasswordToken, 
            resetPasswordExpires: {$gt: Date.now()},
        }, {
            // resetPasswordToken: undefined,
            // resetPasswordExpires: undefined,
            password
        });
        passport.authenticate('local', function(error, user, info) {
            console.log("error", error);
            console.log("user", user);
            console.log("info", info);
            if (error) {
                return next(error);
            }
            if (!user) {
                return handleError(res, "There was a problem resetting your password.  Please try again.", {error_code: 401, error_message: "There was a problem resetting your password.  Please try again."}, 401);
            }
            req.logIn(user, function(error) {
                if (error) {
                    return next(error);
                }
                return res.redirect('/admin/#/');
            });
        })(req, res, next);
    } catch(error) {
        console.error(error);
        handleError(res, error.message, "/reset");
    }
});

我是 运行:

"mongoose": "^4.8.4",
"express": "~3.3.4",
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"passport-local-mongoose": "^4.1.0",

"node": "7.9.0"

对于遇到此问题的其他人。我最终自己找到了解决方法。我需要使用 setPassword():

app.post('/reset', async function(req, res, next) {
    try {
        var resetPasswordToken = req.body.resetPasswordToken;
        var username = req.body.username;
        var password = req.body.password;
        var user = await User.findOneAndUpdate({
            username,
            resetPasswordToken, 
            resetPasswordExpires: {$gt: Date.now()},
        }, {
            resetPasswordToken: undefined,
            resetPasswordExpires: undefined,
        });
        user.setPassword(password, (error, user) => {
            if (error) {
                return next(error);
            }
            user.save((err, user) => {
                if (error) {
                    return next(error);
                }
                passport.authenticate('local', function(error, user, info) {
                    console.log("error", error);
                    console.log("user", user);
                    console.log("info", info);
                    if (error) {
                        return next(error);
                    }
                    if (!user) {
                        return handleError(res, "There was a problem resetting your password.  Please try again.", {error_code: 401, error_message: "There was a problem resetting your password.  Please try again."}, 401);
                    }
                    req.logIn(user, function(error) {
                        if (error) {
                            return next(error);
                        }
                        return res.redirect('/admin/#/');
                    });
                })(req, res, next);
            });
        });
    } catch(error) {
        console.error(error);
        handleError(res, error.message, "/reset");
    }
});