Node.js and Passport Object has no method validPassword

Please note that I'm a total beginner in Node.js so please be patient with me :)

I'm using Node.js + Express 3 + Passport to create a simple authentication(local) just to play around

and what I've reached so far that when a wrong username or password entered user is redirected to an error page

but when the user enters a correct username and password I get this error

node_modules\mongoose\lib\utils.js:435
    throw err;
          ^
TypeError: Object { _id: 50b347decfd61ab9e9e6768f,
username: 'saleh',
password: '123456' } has no method 'validPassword'

I'm not sure what's wrong there

app.js (I removed the unnecessary code):

  var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

  app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});



var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'authTest');

var authSchema = mongoose.Schema({ 
  username: 'string',
  password: 'string'
});

var User = db.model('users', authSchema);


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



passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});




app.post('/login',
  passport.authenticate('local', { successRedirect: '/',
                                   failureRedirect: '/login/error',

                                  })
);

and now in routes/login.js

var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'authTest');

var authSchema = mongoose.Schema({ 
    username: 'string',
    password: 'string'
});

var User = db.model('users', authSchema);

exports.index = function(req, res){
User.find(function (err, list) {
        res.render('login', { title: 'Usernames and Passwords', users: list,msg:""});
    });
};

Thanks for your time.

Looks like you copied example from passportjs website, where Jared failed to mention how to implement it..

On passport js github page he has another (simpler) example he removed validPassword method altogether (line 65):

https://github.com/jaredhanson/passport-local/blob/master/examples/login/app.js

if (user.password != password) { return done(null, false, { message: 'Invalid password' }); }

That's what I based my app on (using encryption) on top of it.

Well, this is kind of obvious, isn't it? You are using

if (!user.validPassword(password)) {
    return done(null, false, { message: 'Incorrect password.' });
}

but you haven't defined validPassword method. Attach it to your schema:

var authSchema = mongoose.Schema({ 
    username: 'string',
    password: 'string'
});
authSchema.methods.validPassword = function( pwd ) {
    // EXAMPLE CODE!
    return ( this.password === pwd );
};

EDIT You've also incorrectly defined the schema. It should be:

var authSchema = mongoose.Schema({ 
    username: String,
    password: String
});

Note that both username and password should be String type objects, not strings "string", if you know what I mean. :)

Also being a noob at this, it took me a whole day to figure this one out. I used the history from another one of Jared's example apps and some crypto advice from folks on here.

First off I made a method that generates a salt (a big random number which is stringified), uses the salt and the user's password to create a hash (with the help of the nodejs 'crypto' module), and finally stores both the salt and the hash every time before mongoose saves a new account.

//make hash
userSchema.pre('save', function(next) {
    var user = this;
    if(!user.isModified('password')) return next();
    var rand = (Math.floor(Math.random() * 1000000000)).toString(36);
    var hash = crypto.createHash('md5').update(user.password + rand).digest("hex");
    user.password = hash;
    user.salt = rand;
    next();
});

For the verification I simply take the inputted password (at login) and attempt the make the same hash again using the salt. I then compare the stored hash to the new one and return true or false accordingly.

 // Password verification
    userSchema.methods.validPassword = function(password) {
      var testhash = crypto.createHash('md5').update(password + this.salt).digest("hex");
      if(testhash === this.password) {
        return true;
      } else {
        return false;
      }
    }