Reputation: 146
I'm still a noob to node and webdev, but trying hard!
I get this error : can't set headers after they are sent
with the following while using passport.js and bcryptjs compare method for password validation on a mean stack
routes/login.js
var express = require('express')
var router = express.Router()
var mongoose = require('mongoose')
var User = mongoose.model('User')
var passport = require('passport')
router.post('/', function (req, res, next){
passport.authenticate('local', function(err, user, info){
if(err){ return next(err); }
if(user){
return res.json({token: user.generateJWT()});
} else {
return res.status(401).send(info)
}
})(req, res, next);
});
module.exports = router
authenticate/local.js
var passport = require('passport')
var LocalStrategy = require('passport-local').Strategy
var mongoose = require('mongoose')
var User = mongoose.model('User')
var bcrypt = require('bcryptjs')
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: {
username: 'Incorrect username.'
}
})
}
bcrypt.compare(password, user.password, function(err, isMatch) {
if (err) {
return done(err)
}
if (!isMatch) {
return done(null, false, {
message: {
password: 'Incorrect password'
}
})
}
});
return done(null, user);
});
}));
This validates correctly for a valid username and password, and logs in.
For an invalid username, it correctly rejects the login attempt.
But for an invalid password, it logs in and then crashes the app with the Can't set headers error.
However if i change the bcrypt.compare to bcrypt.compareSync, then all validations are correct.
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false, {
message: {
password: 'Incorrect password'
}
});
}
I would rather not depend on the sync methods, so help me please understand where I am going wrong!
Upvotes: 1
Views: 683
Reputation: 106696
bcrypt.compare()
is async but you're calling done(null, user)
immediately. Move it inside the callback and it should be fine:
bcrypt.compare(password, user.password, function(err, isMatch) {
if (err) { return done(err) }
if (!isMatch) {
return done(null, false, { message: { password: 'Incorrect password' } })
}
done(null, user)
})
Upvotes: 3