title: Node.js Passport strategy login with either Email or Username
body: <p>I am using Passport on my node.js app and I am currently using an Username to login.</p>
  
  <p>On my user register page, I have allow the user to register their unique username and email. </p>
  
  <p>I want a login page with "Sign in Using username/email:" <strong><em>_</em>__<em>_</em>__<em>_</em>_</strong></p>
  
  <p>Where the script can detect if there is a "@" in the field and look up the email instead of username.</p>
  
  <p>I have tried for a few hours with no avail.</p>
  
  <p>here is my passport.js</p>
  
  <pre><code>var mongoose = require('mongoose')
  var LocalStrategy = require('passport-local').Strategy
  
  var User = mongoose.model('User');
  
  module.exports = function(passport, config){
  
  passport.serializeUser(function(user, done){
      done(null, user.id);
  })
  
  passport.deserializeUser(function(id, done) {
      User.findOne({ _id: id }, function (err, user) {
          done(err, user);
      });
  });
  
  passport.use(new LocalStrategy({
      usernameField: 'username',
      passwordField: 'password'
      }, function(username, password, done) {
      User.isValidUserPassword(username, password, done);
      }));
  }
  </code></pre>
  
  <p>EDIT: below is the user.js as requested</p>
  
  <pre><code>var mongoose = require('mongoose');
  var hash = require('../util/hash.js');
  
  UserSchema = mongoose.Schema({
  username:  String,
  email:      String,
  salt:       String,
  hash:       String
  })
  
  UserSchema.statics.signup = function(username, email, password, done){
  var User = this;
  
  hash(password, function(err, salt, hash){
      if(err) throw err;
      // if (err) return done(err);
      User.create({
          username : username,
          email: email,
          salt : salt,
          hash : hash
      }, function(err, user){
          if(err) throw err;
          // if (err) return done(err);
          done(null, user);
      });
  });
  }
  
  UserSchema.statics.isValidUserPassword = function(username, password, done) {
  this.findOne({username : username}, function(err, user){
      // if(err) throw err;
      if(err) return done(err);
      if(!user) return done(null, false, { message : 'Incorrect username.' });
      hash(password, user.salt, function(err, hash){
          if(err) return done(err);
          if(hash == user.hash) return done(null, user);
          done(null, false, {
              message : 'Incorrect password'
          });
      });
  });
  };
  
  var User = mongoose.model("User", UserSchema);
  
  module.exports = User;
  </code></pre>