Joseph
Joseph

Reputation: 1976

How to authenticate via email rather than username in passport.js?

I am currently using this code for logging in:

passport.use(new localStrategy({
  usernameField: 'username'
}, User.authenticate()));

That works fine when I login with username and password. Now I want to login with email rather than username. I've changed my code to this:

passport.use(new localStrategy({
  usernameField: 'email',
  usernameQueryFields: ['email']
}, User.authenticate()));

I've also changed my HTML code to display email field with the name of email:

<input type="text" name="email" id="email" placeholder="Your Email" class="form-control">

and here's my users' schema:

{
    "_id" : ObjectId("585f62d63158ec1f608f82a2"),
    "salt" : "d7fd24ab337be7341bb6c54df69eccdce607a6cffc8457be4d44",
    "hash" : "(long text)",
    "username" : "joseph320",
    "email" : "[email protected]",
    "name" : "joseph",
    "__v" : 0,
}

So now it should look for email field in database and compare that with the email user provided in login form. But it doesn't work. When I try to login with email and password it gives me 'invalid username or password' error.

But when I am try to login with the username and the exact password it will successfully log me in. Where is the problem and how can I solve the problem?

I am using this packages for authentication:

"passport": "^0.3.2",
"passport-local": "^1.0.0",
"passport-local-authenticate": "^1.2.0",
"passport-local-mongoose": "^4.0.0",

Upvotes: 8

Views: 9338

Answers (3)

Josiah
Josiah

Reputation: 61

I struggled with this one for a bit. It's important that you have the usernameField defined in TWO places:

  1. When creating your localStrategy (as in Joseph's original question):

    passport.use(new localStrategy({
        usernameField: 'email'
    }, User.authenticate()));
    
  2. When defining your user model (as in robertklep's answer):

    userSchema.plugin(passportLocalMongoose,
    {
        usernameField: 'email'
    });
    

Upvotes: 6

Burdy
Burdy

Reputation: 611

By default, LocalStrategy expects to find credentials in parameters named username and password. If your site prefers to name these fields differently, options are available to change the defaults.

Read more:

passport.use(
        'local-signup',
        new LocalStrategy({

            usernameField : 'email',

            passwordField : 'password',

            passReqToCallback : true 
        },
        function(req, username, password, done) {

            User.findOne({email: 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);
            })

        })
)

Upvotes: 3

robertklep
robertklep

Reputation: 203304

From what I understand, you need to tell passport-local-mongoose which field to use:

User.plugin(passportLocalMongoose, { usernameField : 'email' });

(doc)

And also use it to create the strategy for you:

passport.use(User.createStrategy());

(doc)

Upvotes: 8

Related Questions