passport.js - authenticate users from MongoDB with passport-local

我的梦境 提交于 2019-12-30 07:31:29

问题


I have a simple users collection in my MongoDB. I user mongo-native driver.

{
    "email": "johndow@example.com",
    "password": "123456",
    "_id": {
        "$oid": "50658c835b821298d3000001"
    }
}

As I user auth via pair email:pass, I re-wrote default passport-local function findByUsername to this:

function findByEmail(email, fn) {
    db.collection("users", function(err, collection) {
        collection.find({}, {}, function(err, users) {
            users.each(function(err, user) {
                if (user.email === email) {
                    return fn(null, user);
                }
            });
            return fn(null, null);
        });
    });
}

Just get all of the users form DB, and checking - if user.email == provided email, then return user object.

I use _id parameter of MongoDB as id for users, that's why I've modifies these two functions:

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

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

And this is my code for passport local strategy:

passport.use(new LocalStrategy( function(email, password, done) {
    process.nextTick(function() {
        console.log('initialize findByEmail() for "',email,'"');
        findByEmail(email, function(err, user) {
            if (err) {
                return done(err);
            }
            if (!user) {
                console.log('Unknown user ' + email)
                return done(null, false, {
                    message: 'Unknown user ' + email

                });
            }
            if (user.password != password) {
                console.log('Invalid password')
                return done(null, false, {
                    message: 'Invalid password'
                });
            }
            //сonsole.log('ALL VERIFIATION PASSED');
            return done(null, user);
        })
    });
}));

I post data from login page:

app.post('/login', passport.authenticate('local', {
    failureRedirect: '/',
    failureFlash: true
}), function(req, res) {
    res.redirect('/desk');
});

And I get

Error: Can't set headers after they are sent.

and after this I get

TypeError: Cannot read property 'email' of null

The last error is really strange 'cause findByEmail has console.log(user) line (removed from this listing) and it list all the user's data.

What am I doing wrong?


回答1:


It's not well documented, but cursor.each provides a null value to the second parameter of its callback to indicate that the cursor has no more documents available. It's only mentioned in the example of the documentation.

So in your case you should be checking for user !== null in your users.each callback.

However, it would be more efficient to have mongo do the searching for you by changing your find call to:

collection.findOne({email: email}, {}, function(err, user) {
    if (user) {
        // email was found case
        ...
    }
    ...
}


来源:https://stackoverflow.com/questions/12639476/passport-js-authenticate-users-from-mongodb-with-passport-local

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!