"Error: Illegal arguments: string, undefined" and stop server in node JS

Viewed 22484

I'm trying to build logging application in node JS. in here password authentication app do not work properly. when i enter username and password it occur following error and stop server.

this is the error.

enter image description here

Here is the code for authentication part

passport.use(new LocalStrategy(
function(username, password, done) {
    User.getUserByUsername(username, function(err, user){
       if(err) throw err;
       if (!user) {
           return done(null, false, {message: 'Unknown user'});
       } 

       User.comparePassword(password, user.password, function(err, isMatch){
           if(err) throw err;
           if (isMatch) {
               return done(null, user);
           } else {
               return done(null, false, {message: 'Invalid password'});
           }
       });
    });
}));

This code work for Unknown user. but it is not working for comparing username and password. i cannot see any bug in here. i want a help for solve this.

8 Answers

In the name of the universe programmer

in my case i forgot to select the password because in database the password was ((select: false))

this code for app

const user = await User.findOne({email}).select("+password")

i forgot to append the ((.select("+password")))to the findOne

and I received this error ; Error: Illegal arguments: string, undefined

and this code for database

const User = new mongoose.Schema({
    username:{
        type:String,
        required: [true,"نام کاربری ضروری است"]
    },
    email:{
        type:String,
        required: [true,"رایانامه ضروری است"],
        unique: true,
        match:[
            /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,3})$/,
            "لطفا یک رایانامه صحیح وارد کنید"
        ]
    },
    password:{
        type:String,
        required:[true,"رمز ضروری است"],
        minlegth: 5,
        select: false
    }
})

In my case, I was using arrow function

userSchema.methods.comparePassword = async (enterdPassword) => {
  return await bcrypt.compare(enterdPassword, this.password);
};

which I converted to normal function

userSchema.methods.comparePassword = async function (enterdPassword) {
  return await bcrypt.compare(enterdPassword, this.password);
};

that solved the problem

In my case, I'm using social signin/signup. When the user is signing up using a social login option, the value of the password stored is "NULL".

So I just added this little check :

  comparePassword: function(password, user){
    if (!user.password)
      return false;
    return bcrypt.compareSync(password, user.password);
  }

At

"models/user.js"

Inside comparePassword

module.exports.comparePassword = (candidatePassword, hash, callback) => {...) 

Add this code:

bcrypt.hash(candidatePassword, 10, (err, hash) => {
    if(err) {
        throw err;
    }
    bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
        if(err) {
            throw err;
        }
        callback(null, isMatch);
    });
});

Here We are grabbing username and password from the sign in page AND finding our user by the username from the database and then Matching its encrypted password with an entered password by the user

passport.use(new LocalStrategy(
    (username,password,done)=> {
        db.users.findOne({username: username},(err, user)=> {
            if(err) return done(err);

            if(!user) {
                return done(null,false,{message: 'Incorrect Username'});
            }
            bcrypt.compare(password, user.password,(err,isMatch)=> {
                if(err) return done(err);
                if(isMatch) {
                    return done(null, user);
                } else {
                    return done(null, false,{message: 'Incorrect Password'});
                }
            });
         });
      }
   ));

You need to apply await to your salt and password assignments too.

Like this,

const salt = await bcrypt.genSaltSync(10);
const password = await req.body.password;

You can write a code like this: After this.findOne({ select: [] ........}) ... I hope this is helpful

async validateUserPassword(loginDto: AuthLoginDto): Promise<User> {
    const { mobile, email, password } = loginDto;
    const user = await this.findOne({
      select: ['id', 'email', 'mobile', 'password', 'salt', 'status', 'logged_at'],
      where: [
        { mobile: mobile },
        { email: email }
      ]

    });

    if (user && await user.validatePassword(password)) {
      const logged_at = {
        logged_at: new Date()
      }
      await this.update({ id: user.id }, logged_at)
      return user;
    } else {
      return null;
    }
  }
  
  async validatePassword(password: string): Promise<boolean> {
    const hash = await bcrypt.hash(password, this.salt);
    return hash === this.password;
  }

Related