Question

I'm trying to implement local auth using Compoundjs, Passportjs (compound-passport) and Bcryptjs. Here is my code:

define new strategy

var Strategy = require('passport-local').Strategy;
passport.use(new Strategy({
    usernameField: conf.usernameField || 'email'
}, exports.callback));

callback function

exports.callback = function (email, password, done) { 
    exports.User.findOrCreate({
        email: email,
        password: password
    }, function (err, user) {
        if (err) {
            return done(err);
        }
        if (!user) {
            return done(err, false);
        }
        var len = exports.User.verifyPassword.length;
        if (len === 2) {
            if (!exports.User.verifyPassword(password, user.password)) {
                return done(err, false);
            } else {
                return done(err, user);
            }
        } else if (len === 3) {
            exports.User.verifyPassword(password, user.password, function(err, isMatch) {
                return done(err, !err && isMatch ? user : false);
            });
        }
        return done(err, false);
    });
};

User.verifyPassword

User.verifyPassword = function verifyPassword(password, hash, cb) {
    bcrypt.compare(password, hash, function(err, isMatch) {
        if(err) return cb(err);
        return cb(null, isMatch);
    });
};

In this case i get following error:

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

It refers to redirect after success login. If i use verifyPassword without callback (sync mode) it works fine:

User.verifyPassword = function verifyPassword(password, hash) {
    return bcrypt.compareSync(password, hash);
};

Where is error in my code?

Was it helpful?

Solution

You probably need to add an else statement for your last call to done() as indicated in this snippet:

if (len === 2) {
    if (!exports.User.verifyPassword(password, user.password)) {
        return done(err, false);
    } else {
        return done(err, user);
    }
} else if (len === 3) {
    exports.User.verifyPassword(password, user.password, function(err, isMatch) {
        return done(err, !err && isMatch ? user : false);
    });
}
else {
    // Added an ELSE statement here
    return done(err, false);
}

Without this else statement the call to exports.User.verifyPassword() will be made AND the call to return done(err,false)...and then eventually a second call to done() will be made when verifyPassword() calls the callback that you gave it.

The second call to done() is what is probably producing the headers have been set error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top