29

I am getting a bcrypt error stating that data and hash arguments are required, referencing line #44 in my routes.js file. From what I can tell, I am passing that information: the first parameter to bcrypt.compare is the user entered password, and the second is the hashed password retrieved from the db. What am I doing wrong?

bcrypt.compare(req.params.password, user.password, function...

routes.js

'use strict'

var express = require('express');
var router = express.Router();
var User = require('../app/models/user');
//password hashing
var bcrypt = require('bcrypt');

var count = 0;

router.use(function(req, res, next) {
    count++;
    console.log('API hit count = %s', count);
    next();
});

// /users post(create new user) get(specific user)
router.route('/users')
    .post(function(req,res) {
        var user = new User();
        user.username = req.body.username;
        user.password = bcrypt.hashSync(req.body.password, 10);

        //save the user and checkfor errors
        user.save(function(err) {
            if (err) {
                res.send(err);
            } else {
                res.json({message: "User created!"});
            }    
        });

    })

router.route('/users/:username')
    .get(function(req, res) {
        var query = {
            username: req.params.username,
        };
        User.findOne(query, function(err, user) {
            if (err) { 
                res.send(err);
            } else {
                bcrypt.compare(req.params.password, user.password, function(err, res) {
                    if(err) {
                        console.log('Comparison error: ', err);
                    }
                })
                res.json(user);
            }
        });
    })
johnny_mac
  • 1,801
  • 3
  • 20
  • 48
  • 2
    Set a breakpoint right before `bcrypt.compare` is called and see what `req.params.password` and `user.password` are. – bejado Feb 15 '17 at 05:10
  • 1
    @bejado Dammit, I had a mistake in my app.js, sending in an undefined password. Thanks for helping. – johnny_mac Feb 15 '17 at 05:18

16 Answers16

46

bcrypt.compare takes 3 parameters; passwordToCheck, passwordHash, and a callback, respectively. (Check the documentation for examples)

This error means one or both of the first 2 parameters are either null or undefined. Therefore, make sure both of them are passed correctly. (Not as null or undefined)

u-ways
  • 6,136
  • 5
  • 31
  • 47
sapy
  • 8,952
  • 7
  • 49
  • 60
  • 4
    This can also happen when you are using `arrow function` syntax, instead of normal `function()` syntax. So, make sure to use the latter syntax if you want to preserve `this` coming from the model, i.e., when pulling something out of the current schema. This saved my day. Thanks!!! – Shivam Jha Oct 09 '20 at 09:09
  • The await syntax does not require the third argument. My issue was one of the two arguments did not have the value I expected, so fixing that fixed this issue. – aderchox Mar 29 '22 at 07:01
8

Why do we face this error? bcrypt Error: data and hash arguments required

Example: bcrypt.compare(first, second)

Ans: because either second key hash password does not exist (null or undefined) or first, which are compared to each other.

Ali Bin Naseer
  • 113
  • 2
  • 8
Mirza Hayat
  • 284
  • 5
  • 11
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). – Tyler2P Aug 13 '21 at 12:02
5

I used

const user = await User.find({email: req.body.email}) //which returned all users

//and unless i reference the first user in index 0, i can't pass user.password to the //bcrypt compare method because it's not a string I changed it to

await User.findOne({email: req.body.email})//from which i can use user.password in the //bcrypt compare method
2mighty
  • 149
  • 2
  • 5
3

I was having the same error when I was working with node js and mongoose. It was caused by attribute added to password called select: false in user model.

After remove it, it works.

ncutixavier
  • 455
  • 5
  • 4
2
const passwordMatch = await bcrypt.compare(password, user.password);

Make sure you are giving raw password and hash password. This will return a boolean value.

Caffeines
  • 169
  • 2
  • 5
0

I had the same error and the problem was a missing await when calling the function that reads from database

Riccardo
  • 1,083
  • 2
  • 15
  • 25
0

I was having the same issue, but I was using the synchronous form of bycrypt.compare(), which is bcrypt.compareSync(), so I changed it to bcrypt.compare() and it works perfectly.

Ethan
  • 876
  • 8
  • 18
  • 34
0

the steps for this problem : 1-ensure that the bcrypt function is have awir before it 2- if the problem is still exist ,then the problem is in the database (mongodb),try to create new database an example:

const match = await bcrypt.compare(password,userValid.password);
            if (match) {
                res.send("login successful")
            }else{
                res.send("wrong password")
            }
        }
0

Use

findOne({})

instead of

find()

Try console.log() to view and verify the data.

cursorrux
  • 1,382
  • 4
  • 9
  • 20
mza
  • 46
  • 6
0
try {
    let match  = await bcrypt.compare(password, user.password)
    if(!match){
        return  res.json({mass: "invalid Created"})
    }else{
       res.send('Wrong password')
    }

    console.log('success fulli', user)
    res.render('pages/auth/login', {title: 'Login In Your Account'})

} catch(e) {
    console.log(e)
    next(e)
}
Mahyar Mottaghi Zadeh
  • 1,178
  • 6
  • 18
  • 31
0

The problem also can appear when you forget to add await when loading data from the database. I got the same error after forgetting to add "await".

let user = User.findOne({ username: req.body.username });

let user = await User.findOne({ username: req.body.username });

Freedisch
  • 124
  • 1
  • 9
0

I also have this problem i set for password select:false in user model and solved by adding select('+password') to login route

Natnael
  • 17
  • 7
0

i know all the questions are solved but maybe someone finds this code works for him

const passwordMatch = await bcrypt.compare(password, user.rows[0].s_password);

The name after the dot it's the name you use in your database, it's the field

Roel Leal
  • 49
  • 2
0

I had the same issue, found out that I had missed an await while comparing hence receiving a null value when comparing.

// Compare incoming & stored password
const matchedPassword = await bcrypt.compare(password, userExists.password)

Also, the first argument should be the plain text password while the second is the hashed password.

0

Okay guys huddle up!

First of all if you have "select":false for password in your schema, you should use it like this:

const {email,passord} = req.body

const user = await User.findOne({ email }).select('+password'); // that will allow us the edit password property without revealing it.

After that you can call your compare function

if (!(await user.comparePassword(password, user.password))) {
      res.status(400).json({
        status: 'Fail',
        msg: 'Incorrect nickname or password',
      });
    }
0

I also faced the same problem. I realized that usermodel.find() returns an array of all users but users.findOne() returns an object. You should use the latter.