Wrong password when log in – Bcrypt

Issue

I am making a login route with mongoose and express. When I create an account, the password is hashed by bcrypt. When I log in, I need to compare them. So here is my try :

const mongoose = require("mongoose");
const bcrypt = require("bcrypt");

const UserSchema = new mongoose.Schema(
  {
    email: {
      type: String,
      required: [true, "L'e-mail est requis"],
      unique: true
    },
    password: {
      type: String,
      required: [true, "Le mot de passe est requis"]
    },
    firstname: {
      type: String,
      required: [true, "Le prénom est requis"]
    },
    lastname: {
      type: String,
      required: [true, "Le nom est requis"]
    }
  },
  { collection: "users" }
);

UserSchema.pre("save", async function(next) {
  const user = this;
  const salt = await bcrypt.genSalt(10);
  const hash = await bcrypt.hash(user.password, salt);
  user.password = hash;
  next();
});

UserSchema.methods.isValidPassword = async function(password) {
  const user = this;
  const compare = await bcrypt.compare(password, user.password);

  return compare;
};

module.exports = mongoose.model("User", UserSchema);

The problem is, my route returns "Wrong password".
Here is the controller :

module.exports.signIn = async (req, res) => {
  const { email, password } = req.body;
  const user = await UserModel.findOne({ email });

  if (!user) {
    return res.status(400).json({
      message: "email not found."
    });
  }
  if (user.password !== password) {
    return res.status(400).json({
      message: "wrong password."
    });
  }

  res.status(200).json({
    message: "User signed in."
  });
};

It is like my request doesn’t go by UserSchema.methods.isValidPassword. Any idea why ?

Solution

This block:

 if (user.password !== password) {
    return res.status(400).json({
      message: "wrong password."
    });
  }

just compare the password in the request with the hash password stored in your database. The condition is true so you have the message "wrong password".

You need to call the method isValidPassword explicitly.

 const isValidPassword = await user.isValidPassword(password);
 if (!isValidPassword) {
    return res.status(400).json({
      message: "wrong password."
    });
  }

Quick side note: You shouldn’t have 2 different messages for email not found and the wrong password. This allows users to know if the email exists and execute a brute force attack. I suggest something like "Email or password is incorrect" instead.

Answered By – Đăng Khoa Đinh

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published