1

I am using "bcrypt": "^3.0.4" and I have the latest stable version of node. The issue I am facing is when the user attempts to login. With the correct password the initial login attempt is always unsuccessful while the second attempt is successful. I would like to know where I am getting it wrong. The assumption here is that the user has entered an email/username that is available in the database, mongodb in this case.

User.findOne({ "email": user.email }, (err, ruser) => {
    if (err) {
        res.send(err);
    }
    else {
        bcrypt.hash(user.password, 10, function (err, hash) {
            if (err) {
                console.log(err);
            }
            else {
                bcrypt.compare(user.password, hash).then(function (res) {
                    if (res) {
                        pass = true;
                    }
                    else {
                        pass = false;
                    }
                });
                res.json(pass);
            }
        });
    }
});

Thank you in advance.

2
  • Can you post logs at failure time Commented Feb 8, 2019 at 14:09
  • @Shahzeb There are no errors in the console if that's what you mean. I removed the hash part i.e. bcrypt.hash(user.password, 10 .. and retried, but the outcome is the same. console.log(ruser.password) shows the password as retrieved from the database. Commented Feb 8, 2019 at 15:06

2 Answers 2

2

There are two issues with your code.

  1. bcrypt.compare is async and the res.json is outside of the .then, so res.json is actually ran before comparison or pass it set.

  2. pass is not defined with var/let, so pass becomes a global variable and this is serious security implication, because two user logging in at the same time will cause a race condition (e.g. pass from session A may be res.json-ed in session B)

It works as a result of the above two errors, in the first request, res.json is executed before comparison and pass is not set yet, so it returns null. On the second request, again res.json is executed before compare, however this time the pass contains the value of the last compare, so what you are getting is actually last compare's result.

In addition, it is ok if you are just testing, otherwise this code does nothing, because this code generates the hash for the given password, and compares the given password to the generated hash, which definitely should be always true.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Eric. Correct I am just testing at the moment. So I tried to change it up a bit. bcrypt.compare(password, hash, function (result) { wherein hash is the retrieved hashed password from the database and password is the password the user entered in the form. Why is the compare not working ? I went through the bcrypt documentation and the mini example there seems clear enough. What am i missing ? I am referring to bcrypt.compare here.
0
import { hash, compare } from 'bcryptjs';

export const hashPassword = async (password: string): Promise<string> => {
  const hashedPassword = await hash(password, 10);
  return hashedPassword;
};

1 Comment

Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.