Issue
So I’m using passport-local and express to handle user log-in. So far I have been able to get a successful log-in while using usernames, but usernames are hard to remember and I personally don’t think they should be used for handling users, so I tried modifying the sample Strategy provided on the passport-local page to confirm users via email, but the code doesn’t work.
The strategy I have for emails is:
passport.use(new LocalStrategy(function(email, password, done) {
User.findOne({ email: email }, {}, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + e }); }
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
And It’s derived from this strategy:
//The login strategy
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: 'Unknown user ' + username }); }
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
So the username strategy works perfectly fine, but the email one is not. I even left a console.log() in both the username and email strategy to see what the strategies were returning. The Username strategy returns all information on the user, while the email strategy returns
false
. I have no idea why the site is doing this, and none of the solutions I’ve seen so far work.
One solution I’ve seen on another post suggested that I just use the
findOne({email: email}, function(err, user){
});
option to login with the email to find the user, but it hasn’t been working at all.
Here is the Jade file I use to take input from the user:
extends layout
block content
h1 Login
form(action= '/login', method='post')
p Email
br
input#email(type='text',value='',placeholder='@',name='email')
p Password
br
input#password(type='password',value='',placeholder='Password',name='password')
input(type='submit') Submit
And here is the POST input:
// POST /login
// This is an alternative implementation that uses a custom callback to
// acheive the same functionality.
exports.postlogin = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
req.session.messages = [info.message];
return res.redirect('/login')
}
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/');
});
})(req, res, next);
};
What the heck is going on here? With email it should be working perfectly. Also since I’m asking a question anyway, how do I confirm the email after somebody had registered?
Solution
It seems to me you just changed the name of the argument in the LocalStrategy callback to “email”. Passport doesn’t automagically know that the field is named email though, you have to tell it.
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.
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'passwd'
},
function(username, password, done) {
// ...
}
));