Search code examples
javascriptnode.jsexpressjwtbcrypt

bcrypt.compare promise always returns false


I've looked through the other issues with bcrypt.compare on GitHub and none of the solutions have worked for me. It always fails on console.log("failed 3") inside bcrypt.compare()

I've tried switching the .then() instead of using a callback with bcrypt.compare as suggested by another post but that hasn't help. Any help would be greatly appreciated!

Below is a copy of my code and summary of versions being used:

  • Node v8.12.0
  • Express 4.16.0
  • bcrypt 3.0.3
  • jsonwebtoken 8.4.0
  • mongoose 5.4.1

Bcrypt Hash (Password Hashing)

function saveUserData(req, res, next, userSignUpInfo, info){
bcrypt.hash(req.body.email, 10, (err, hash) =>{ 
if (err){   
  return res.status(500).json({
    error: err
  })
} else {
  console.log('inside test route')
  console.log('req.body.fnUserName', userSignUpInfo.fnUserName)
  const userData = new UserData({
    fnUserName : userSignUpInfo.fnUserName,
    password : hash,
    email : req.body.email,
    verify: userSignUpInfo.verify,
    createAccountDate: userSignUpInfo.createAccountDate,
    userId : userSignUpInfo.userId,
    friends: null,
    online: null
    })
  userData.save()
    .then(result => {
      console.log('result from MongoDB Cloud', result);
      saveApiData(info, userSignUpInfo, res);
  })
  .catch(err => console.log('error from MongoDB Cloud', err));
}
})
}

Bcrypt Compare (Auth User)

    router.post('/login', (req, res, next) => {
    UserData.find({email: req.body.email})
    .exec()
    .then(user => {
      if(user.length < 1) {
        console.log("failed 1")
     return res.status(401).json({
      message: 'Authentication Failed'
    });
    }
    console.log('user[0].password', user[0].password)
    console.log(' user[0].password',  user[0].password)
    console.log(' req.body.password',  req.body.password)

    bcrypt.compare(req.body.password,user[0].password).then(function(err, result) {
    if (err) {
      console.log("failed 1")
      return res.status(401).json({
        message: 'Authentication Failed'

      });
    }
    if (result) {
      const token = jwt.sign(
        {
        email: user[0].email,
        userId: user[0].userId
        },
        process.env.JWT_KEY,
        {
          expiresIn: "1h"  // he suggested one hour
        }
      );
      console.log("failed 2")
      return res.status(200).json({
        message: 'Authentication Successful',
        token: token
      })
    } else {
      console.log("failed 3")
      res.status(401).json({
        message: 'Authentication Failed'
      })
    }
    })
    })
     .catch(err => {
     console.log('err in login', err);
     res.status(500).json({
      error: err,
      message: 'error logging in'
    })
     })
    });

Solution

  • result will always be undefined since promises return a single value and errors are simply thrown in the catch phrase. So basically, in your code, err will contain the actual result.
    What your code should look like is the following:

    bcrypt.compare(req.body.password,user[0].password).then((result)=>{
      if(result){
        console.log("authentication successful")
        // do stuff
      } else {
        console.log("authentication failed. Password doesn't match")
        // do other stuff
      }
    })
    .catch((err)=>console.error(err))