简体   繁体   中英

Error: req#login requires a callback function Passport.js

I'm implementing a passport reset but req.login doesn't seem to be working.

Here is my route

// Token URL :post
router.post('/users/reset/:token', (req, res, next) => {
  if(req.body.password === req.body['password-confirm']) {
    req.flash('error', 'Passwords do not match!');
    res.redirect('/users/forgot');
  }

  User.findOne({
    resetPasswordToken: req.params.token,
    resetPasswordExpires: { $gt: Date.now() }
  }, function(err, user) {
    if(!user) {
      req.flash('error', ' Password reset is invalid or has expired');
      res.redirect(302, '/login');
    }

    const setPassword = promisify(user.setPassword, user);
    setPassword(req.body.password);
    user.resetPasswordToken = undefined;
    user.resetPasswordExpires = undefined;
    const updatedUser = user.save();

    req.login(updatedUser);

    req.flash('success_msg', 'Your password has been reset successfully! You are now logged in!');
    return res.redirect('/dashboard' + req.user);
  });
});

and here is the logs

Thu Jan 25 2018 22:45:10 GMT+0000 (GMT): GET /users/reset/3eab13651335967925c180427bfb2ccc956187be
Mongoose: users.findOne({ resetPasswordExpires: { '$gt': new Date("Thu, 25 Jan 2018 22:45:10 GMT") }, resetPasswordToken: '3eab13651335967925c180427bfb2ccc956187be' }, { fields: {} })
Thu Jan 25 2018 22:45:10 GMT+0000 (GMT): GET /favicon.ico
Thu Jan 25 2018 22:45:20 GMT+0000 (GMT): POST /users/reset/3eab13651335967925c180427bfb2ccc956187be
Mongoose: users.findOne({ resetPasswordExpires: { '$gt': new Date("Thu, 25 Jan 2018 22:45:20 GMT") }, resetPasswordToken: '3eab13651335967925c180427bfb2ccc956187be' }, { fields: {} })
events.js:136

      throw er; // Unhandled 'error' event
      ^

Error: req#login requires a callback function
    at IncomingMessage.req.login.req.logIn (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/http/request.js:47:44)
    at /Users/benbagley/Code/poetry-out-loud/routes/users.js:326:9
    at model.Query.<anonymous> (/Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/model.js:4056:16)
    at /Users/benbagley/Code/poetry-out-loud/node_modules/kareem/index.js:273:21
    at /Users/benbagley/Code/poetry-out-loud/node_modules/kareem/index.js:131:16
    at process._tickCallback (internal/process/next_tick.js:150:11)
[nodemon] app crashed - waiting for file changes before starting...

In mongoose Model.save() is asynchronous (because it takes time to get to the DB and back). When you do the following...

const updatedUser = user.save();

req.login(updatedUser);

you are not passing the updatedUser to req.login - you are passing an unresolved Promise. This is why the login function fails. req.login is also asynchronous!

You need to wait for the functions to finish before using their results. You can to this in three ways:

1) A callback function - this is what you have passed as the second argument to User.findOne .

user.save((saveError, updatedUser) => {
    // Check if saveError is present here and handle appropriately
    req.login(updatedUser, loginError => {
        req.flash('success_msg', 'Your password has been reset successfully! You are now logged in!');
        res.redirect('/dashboard' + req.user);
    })
});

2) Calling .then on the returned promise, and passing a function to then which will be executed when the promise resolves

 user.save()
     .then(updatedUser => req.login(updatedUser))
     .then(() => {
         req.flash('success_msg', 'Your password has been reset successfully! You are now logged in!');
         res.redirect('/dashboard' + req.user);
      })
      .catch(err => /* handle error */);

3) Using async/await and awaiting the resolution of the promise. The whole function needs to be marked as async, then we can await any functions that return promises:

router.post('/users/reset/:token', async (req, res, next) => {
  try {
      if(req.body.password === req.body['password-confirm']) {
          req.flash('error', 'Passwords do not match!');
          res.redirect('/users/forgot');
      }

      const user = await User.findOne({
          resetPasswordToken: req.params.token,
          resetPasswordExpires: { $gt: Date.now() }
      });

      if(!user) {
          req.flash('error', ' Password reset is invalid or has expired');
          res.redirect(302, '/login');
      }

      const setPassword = promisify(user.setPassword, user);
      await setPassword(req.body.password);

      user.resetPasswordToken = undefined;
      user.resetPasswordExpires = undefined;

      const updatedUser = await user.save();

      await req.login(updatedUser);

      req.flash('success_msg', 'Your password has been reset successfully! You are now logged in!');
      return res.redirect('/dashboard' + req.user);
  } catch (err) {
    // handle error
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM