Node function finishing before Mongoose db find method

Why could the example below be returning the node middle-ware function before my mongoose db lookup function finishes? I am sure this is a async issue but I am a bit lost on why.

Middle-ware js file

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

function isUser(login){
    var UsersSchema =  new Schema({
        user:       String,
        user_type:  String,
        password:   String,
        first_name: String,
        middle_name:String,
        last_name:  String,
        birth_date: Date,
        join_date:  Date
    });

    var UserModel = mongoose.model('users', UsersSchema);

    mongoose.connect('mongodb://localhost/identity');
    mongoose.model('users', UsersSchema);
    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'connection error: '));
    db.once('open', function cb () {    
        UserModel.findOne({'user': login}, function (err, user){
            if (err){ throw err; } 
            console.log('connected to user db and preformed lookup.');
            console.log(user);
            return user;
        });
    });
}

module.exports.authenticate = function (login, password, cb) {
    var user = isUser(login),
        msg;    
    console.log(user);
    if (!user) {
        msg = 'Invalid User';
        cb(null, msg);  
        return;
    }   
    if (user.password != password) {
        msg = 'Invalid Password';
        cb(null, msg);
        return;
    }
    cb(user, null); 
};

Console Output

undefined
Login Failed! : Invalid User
connected to user db and preformed lookup.
{ _id: 51c8e16ce295c5b71ac6b229,
  user: 'bclark@themindspot.com',
  user_type: 'admin_master',
  password: 'enter',
  first_name: 'Brandon',
  middle_name: 'Laurence',
  last_name: 'Clark',
  birth_date: Fri Mar 19 1982 00:00:00 GMT-0800 (PDT),
  join_date: Wed Jun 26 2013 00:00:00 GMT-0700 (PDT) }

db.once and UserModel.findOne are asynchronous functions, hence why you provide an anonymous function that is called when they are done. If you want your isUser function to 'return' the results of these asynchronous functions you will have to make it use a callback as well.

Replace function isUser(login){ with function isUser(login, callback){

and return user; with callback(user).

It is also recommended to not throw errors in asynchronous code, but pass them on with the callback, similar to what db.once and UserModel.find do, like so:

Remove if (err){ throw err; } and replace the callback above with callback(err, user);

While you're at it, since you don't do anything with the error or user anymore, you might as well call UserModel.findOne({'user': login}, callback);

===

The complete thing would become the following. Note that I follow the callback(err, result) convention.

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

function isUser(login, callback){
    var UsersSchema =  new Schema({
        user:       String,
        user_type:  String,
        password:   String,
        first_name: String,
        middle_name:String,
        last_name:  String,
        birth_date: Date,
        join_date:  Date
    });

    var UserModel = mongoose.model('users', UsersSchema);

    mongoose.connect('mongodb://localhost/identity');
    mongoose.model('users', UsersSchema);
    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'connection error: '));
    db.once('open', function cb () {    
        UserModel.findOne({'user': login}, callback);
    });
}

module.exports.authenticate = function (login, password, cb) {
    var user = isUser(login, function(err, user) {
        if (err) {
            cb(err);
        }
        console.log(user);
        if (!user) {
            msg = 'Invalid User';
            cb(msg);  
            return;
        }   
        if (user.password != password) {
            msg = 'Invalid Password';
            cb(msg);
            return;
        }
        cb(null, user); 
    });
};

Finally, consider using (custom) Error objects instead of String messages, google it for explanations as to why.

yes this is a async issue. you may know that node.js every action has a separate thread

in your code you call

var user = isUser(login),

according to You it should return the result from the isUser function but the execution give this function a separate thread and it goes on to the next statement. as on the next statement the user is undefined because it doesn't return anything from the function isUser

so the statement if (!user) { becomes true

to avoid this error you should place isUser in a callback function

means restrict the execution until and unless you get response from the function