user6680
user6680

Reputation: 139

Password recovery not updating to new password - JWT/Nodejs

I'm following this tutorial: and I when I enter an email address, I get an email and I click the link and go to this page. [![enter image description here][2]][2]

As you can see, the id and token are being passed in url correctly and when I click Reset Password, I get [![enter image description here][3]][3]

It shows n:1 as if it updated database password successfully, but the password value never updates in the database and I'm not sure why. I added some console.logs to help track the output and API calls. I appreciate any help.

Here's my code

app.js

//Forgot Password Form

app.get("/api/users/forgotpassword", function(req, res) {
  res.send(
    '<form action="/api/users/passwordreset" method="POST">' +
      '<input type="email" name="email" value="" placeholder="Enter your email address..." />' +
      '<input type="submit" value="Reset Password" />' +
      "</form>"
  );
});

//Forgot password form calls this api to send email

app.post("/api/users/passwordreset", function(req, res) {
  console.log("req.body.email");
  console.log(req.body.email);
  let emailValue = req.body.email;

  if (req.body.email !== undefined) {
    User.findOne({ email: req.body.email }).then(user => {
      if (user) {
        console.log("fetchedUser");
        console.log(user._id);
        var payload = {
          id: user._id,
          email: user.email
        };

        var secret = user.password + "-" + user.passwordCreated;
        var token = jwt.sign(payload, secret);
        console.log("payload");
        console.log(payload);

        var ses_mail = "From: 'Auction Site' <" + emailValue + ">\n";
        ses_mail = ses_mail + "To: " + emailValue + "\n";
        ses_mail = ses_mail + "Subject: Password Reset Request\n";
        ses_mail = ses_mail + "MIME-Version: 1.0\n";
        ses_mail =
          ses_mail + 'Content-Type: multipart/mixed; boundary="NextPart"\n\n';
        ses_mail = ses_mail + "--NextPart\n";
        ses_mail = ses_mail + "Content-Type: text/html; charset=us-ascii\n\n";
        ses_mail =
          ses_mail +
          '<a href="http://localhost:3000/resetpassword/' +
          payload.id +
          "/" +
          token +
          '">Click here to reset password</a>';
        //  /:id/:token

        var params = {
          RawMessage: { Data: new Buffer.from(ses_mail) },
          Destinations: [emailValue],
          Source: "'AWS Tutorial Series' <" + emailValue + ">'"
        };

        ses.sendRawEmail(params, function(err, data) {
          if (err) {
            res.send(err);
            console.log(err);
          } else {
            res.send(data);
          }
        });
      }
      if (!user) {
        return res.status(401).json({
          message: "Auth failed"
        });
      }
    });
  } else {
    res.send("Email address is missing.");
  }
});

//URL Link that lets you change pw

app.get("/resetpassword/:id/:token", function(req, res) {
  console.log("Outputs");

  console.log(req.params.id);
  console.log(req.params.token);

  User.findOne({ _id: req.params.id }).then(user => {
    var secret = user.password + "-" + user.passwordCreated.getTime();
    var payload = jwt.decode(req.params.token, secret);

    if (!user) {
      return res.status(401).json({
        message: "Auth failed"
      });
    }
    console.log("USER FOUND");
    console.log(user);
    fetchedUser = user;
    instagramName = user.instagramName;
    //   return bcrypt.compare(req.body.password, user.password);

    res.send(
      '<form action="/resetpassword" method="POST">' +
        '<input type="hidden" name="id" value="' +
        payload.id +
        '" />' +
        '<input type="hidden" name="token" value="' +
        req.params.token +
        '" />' +
        '<input type="password" name="password" value="" placeholder="Enter your new password..." />' +
        '<input type="submit" value="Reset Password" />' +
        "</form>"
    );
  });
});

//POST API CALL THAT UPDATES PW

app.post("/resetpassword", function(req, res) {
  console.log("MADE IT");
  // TODO: Fetch user from database using
  User.findById(req.body.id).then(user => {
    console.log("USER BELOW");
    console.log(user);

    var secret = user.password + "-" + user.passwordCreated.getTime();
    console.log("SECRET");
    console.log(secret);
    var payload = jwt.decode(req.body.token, secret);

    bcrypt.hash(req.body.password, 10, function(err, hash) {
      if (err) {
        console.log(err);
      }
      newPasswordHash = hash;
      // res.sendStatus(401);

      console.log(newPasswordHash);
      console.log(newPasswordHash);

      User.updateOne({ password: newPasswordHash })
        .then(user => {
          console.log(user);
          res.json(user);
        })
        .catch(err => console.log(err));
    });

    console.log("PAYLOAD");
    console.log(payload);
  });
});






Output
Connected to Database!
req.body.email
[email protected]
fetchedUser
5df11e3f1868b0316c073760
payload
{ id: 5df11e3f1868b0316c073760,
  email: '[email protected]' }
Outputs
5df11e3f1868b0316c073760
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkZjExZTNmMTg2OGIwMzE2YzA3Mzc2MCIsImVtYWlsIjoiYXVjdGlvbnNpdGUzMDAwQGdtYWlsLmNvbSIsImlhdCI6MTU3NjA5OTgzMn0.GSmidGtGn4gZM07ab8AgaL7-NaKcs4T02GoQuIPLoQs
USER FOUND
{ _id: 5df11e3f1868b0316c073760,
  email: '[email protected]',
  password:
   '$2b$10$Do56McP/9h/rLp5VCcEorenZQcGnViam7Y0WX5TGB1y2/sbSfM/Ti',
  instagramName: 'auciotnsite',
  over21: 'Yes',
  role: 'Artist',
  fullName: 'Not Added Yet',
  address1: 'none',
  address2: 'none',
  city: 'none',
  state: 'none',
  zip: 'none',
  passwordCreated: 2019-12-11T16:50:07.304Z,
  __v: 0 }
MADE IT
USER BELOW
{ _id: 5df11e3f1868b0316c073760,
  email: '[email protected]',
  password:
   '$2b$10$Do56McP/9h/rLp5VCcEorenZQcGnViam7Y0WX5TGB1y2/sbSfM/Ti',
  instagramName: 'auciotnsite',
  over21: 'Yes',
  role: 'Artist',
  fullName: 'Not Added Yet',
  address1: 'none',
  address2: 'none',
  city: 'none',
  state: 'none',
  zip: 'none',
  passwordCreated: 2019-12-11T16:50:07.304Z,
  __v: 0 }
SECRET
$2b$10$Do56McP/9h/rLp5VCcEorenZQcGnViam7Y0WX5TGB1y2/sbSfM/Ti-1576083007304
$2b$10$duRLuptSeL1jyroSiV22cuLonrZojN.zsuTkrsGw5umx.jd78ySQW
$2b$10$duRLuptSeL1jyroSiV22cuLonrZojN.zsuTkrsGw5umx.jd78ySQW
PAYLOAD
{ id: '5df11e3f1868b0316c073760',
  email: '[email protected]',
  iat: 1576099832 }```

Upvotes: 0

Views: 173

Answers (1)

Arun Kamalanathan
Arun Kamalanathan

Reputation: 8603

The issue is, the code is not waiting for user.updateOne promise to resolve. try this code:

app.post("/resetpassword", async function(req, res) {
  console.log("MADE IT");
  // TODO: Fetch user from database using
  const user = await User.findById(req.body.id);

  console.log("USER BELOW");
  console.log(user);

  var secret = user.password + "-" + user.passwordCreated.getTime();
  console.log("SECRET");
  console.log(secret);
  var payload = jwt.decode(req.body.token, secret);

  try {
    const updatedResult = await new Promise((resolve, reject) => {
      bcrypt.hash(req.body.password, 10, async function(error, hash) {
        if (error) {
          console.log(error);
          reject(error);
        }
        newPasswordHash = hash;
        // res.sendStatus(401);

        console.log(newPasswordHash);
        console.log(newPasswordHash);

        try {
          const updated = await user.updateOne({ password: newPasswordHash })
          resolve(updated);

        } catch(err) {
          console.log(err)
          reject(err)
        }
      });
    })
    res.json(updatedResult)
  } catch(err) {
    console.log(err);
    // TODO: send a response here
  }
  console.log("PAYLOAD");
  console.log(payload);
});

Upvotes: 1

Related Questions