javascriptmongoosebackendmongoose-schemabcrypt

Bcrypt.hashSync returns false when checking updated password


I want the login to be successful but even though the password is updated in database and is being displayed as changed, the compareSync on bcrypt returns false.

    async login(req: Request, res: Response) {
    let email = req.body.email
    const user = await User.findOne({ email: email })
    if (user) {
      if (user.schema.methods.isVerified) {
        let password: string = req.body.password
        let hashedPassword = user.password
        console.log(password, hashedPassword)
        console.log(user.schema.methods.checkPassword(password, hashedPassword))
        if (user.schema.methods.checkPassword(password, hashedPassword)) {
          res.json(dataResponse({ userId: user.id }, 200, 'Login sucess'))
        } else {
          res.json(dataResponse('', 200, 'Invalid email or password'))
        }
      } else {
        const tokenItem = await Token.findOne({ userId: user.id })
        if (tokenItem) {
          if (tokenItem.schema.methods.isNotExpired) {
            await Token.deleteMany().where({ userId: user._id })
            await tokenController.create({ userId: user._id, email: email })
            res.json(
            dataResponse(null, 406, 'Your\'e account is not verified,a new token has been sent to your email')
          )
          } else {
            await Token.deleteMany().where({ userId: user.id })
            await User.deleteMany().where({ _id: user.id })
            res.json(
              dataResponse(
                '',
                401,
                "Your account doesn't exist, please sign up "
              )
            )
          }
        } else{
            await tokenController.create({ userId: user._id, email: email })
            res.json(
                dataResponse(null, 406, 'Your\'e account is not verified,a new token has been sent to your email')
            )
        }
      }
    } else{
        res.json(dataResponse('', 401, 'This account doesn\'t exist, please sign up'))
    }
  }

  async forgotPassword(req: Request, res: Response) {
    let email = req.body.email 
    let password = req.body.password
    const user = await User.findOne({email:email})
    if(user){
      if(user.schema.methods.isVerified){
        await user.updateOne({ password })
        await user.save()
        res.json(dataResponse('', 200, 'Password reset successful'))
      } else {
        res.json(dataResponse('', 401, 'Your account is not verified please try logging in'))
      }
    } else {
      res.json(dataResponse('', 401, 'This account does not exist.'))
    }
  }

Above is the login functionality that I created to get the user logged in. I am using mongoose middleware to hash the password and check the hashed password

    userSchema.pre('save', function (next) {
  this.password = bcrypt.hashSync(this.password, 10)
  next()
})

For hashing password

    userSchema.methods.checkPassword = function (
  password: string,
  hashedPassword: string
) {
return bcrypt.compareSync(password, hashedPassword)
}

For updating password. Now the problem is when I register and login, it works. However, when I update the password, then the bcrypt returns false.

    async forgotPassword(req: Request, res: Response) {
    let email = req.body.email 
    let password = req.body.password
    const user = await User.findOne({email:email})
    if(user){
      if(user.schema.methods.isVerified){
        await user.updateOne({ password })
        await user.save()
        res.json(dataResponse('', 200, 'Password reset successful'))
      } else {
        res.json(dataResponse('', 401, 'Your account is not verified please try logging in'))
      }
    } else {
      res.json(dataResponse('', 401, 'This account does not exist.'))
    }
  }

That is the method I used to update password.


Solution

  • In this case, the updateOnefunction was bypassing mogoose.save which resulted in the error. It worked when I used user.password = password.

    Answer credit: ruakh