Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bcrypt error: illegal arguments String unidentified

Tags:

node.js

here is my complete code

var express = require('express'),
    app = express(),
    mongoose = require('mongoose'),
    bodyParser = require('body-parser'),
    morgan = require('morgan'),
    webToken = require('jsonwebtoken'),
    bcrypt = require('bcryptjs'),
    assert = require('assert');
    Schema = mongoose.Schema,
    secretKey = "omjdiuwkslxmshsoepdukslsj";

//User Schema
var userSchema = new Schema({
    username: {type: String, required: true, index: {unique:true}},
    password: {type: String, required: true, select: false}
})

userSchema.pre('save', function(next){
    var user = this;

    if(!user.isModified('password')) return next();

    bcrypt.hash(user.password, null, null, function(err, hash){
        if(err) return next(err);

        user.password = hash;
        next();
    })
});

userSchema.methods.comparePassword = function(password){
    var user = this;

    bcrypt.compare(password, user.password, function(err, result){
        if(err){
            console.log(err);
        }
        else {
            console.log("passwords match!");
            return;
        }
    })
}

var userModel = mongoose.model('users', userSchema);


//Connecting to Mongo
mongoose.connect("mongodb://localhost/userstories", function(err){
    if(err) {
        console.log(err);
    }
    else {
        console.log("Connected to database!");
    }
});

//Creating Token
function createToken(user){
    var token = webToken.sign({
        _id: user.id,
        username: user.username
    },  secretKey,{
        expiresIn: 30 * 60 * 1000
    })
    return token;
    }

//Middlewares
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(morgan('dev'));

//Api's

app.post('/signup', function(req, res){    
    var user = new userModel({
        username: req.body.username,
        password: req.body.password
    })

    user.save(function(err){
        if(err){
            console.log(err);
        }

        else{
            res.json({message: "User created!"});
        }
    })
})

app.post('/login', function(req, res){

    userModel.findOne({username: req.body.username}, function(err, user){
        if(err) console.log(err);

            if(!user){
                res.send("User not found!");
            }
                 else if(user){

                      var validPassword = user.comparePassword(req.body.password);

                       if(validPassword){
                                var tokens = createToken(user);

                                res.json({
                                    success: true,
                                    message: "Successfully logged In",
                                    token: tokens
                                });
                        } 

                            else {
                                    res.send("Invalid password");
                                  }

                     }
    })
});


//Running the server
app.listen(3000, function(err){
    if(err) console.log("port not working");
    else{
        console.log("Everything went just fine");
    }
})

I've tried every approaches and saw all the answers here. But no one seem to come across this illegal argument error. Please figure this one out for me Im sure there is a bug I cant see

like image 927
Hanif Punjwani Avatar asked Jan 24 '16 23:01

Hanif Punjwani


3 Answers

In your User Schema, you are setting select to false for the password field. This means that anytime you look for a user in the schema as you're trying to do in the login request, you won't get the value of the password field or any other field that has select false defined in the schema.

What you need to do is to specify you need the password when the user is found:

app.post('/login', function(req, res){
  userModel.findOne({username: req.body.username}, 'password', function(err, user){
   // continue
}

This will return only the _id and the password from the DB. If you want to return other fields, you'd have to add them in:

app.post('/login', function(req, res){
  userModel.findOne({username: req.body.username}, 'password firstName lastName email', function(err, user){
   // continue
}

like image 96
Peoray Avatar answered Oct 14 '22 09:10

Peoray


I have tried the same code for authentication once and got the same error Error: Illegal arguments: string, function.

But I did not see any issue with the code. The thing is, I had registered two users with the same user name and a different password. Then, when I tried to log in with the user name and one password this error occurred and stopped the server.

So it seems that you are also facing the same problem. Make sure there are no errors with this stuff if you do not want to have a bug in your code.

like image 45
Buddhika Priyabhashana Avatar answered Oct 14 '22 09:10

Buddhika Priyabhashana


Check the value of user.password before sending it to bcrypt.compare().

Chances are, you've fetched the user without including the password property, resulting in a value of undefined. This can happen in Sequelize if you set custom attributes or if you're using a scope that excludes props.

like image 3
claviska Avatar answered Oct 14 '22 07:10

claviska