I have made a set up to update a user\'s password using NodeJS/Passport. I followed this great guide: http://sahatyalkabov.com/how-to-implement-password-reset-in-nodejs/.
I already used this code in my current project, and its working fine, I saw a small error in your code in function UserSchema.pre('save', function(next)
. when you hash the password with bcrypt.hash
then it took four arguments but there are only three argument in my code like
schema.pre('save', function(next) {
var user = this;
var SALT_FACTOR = 5;
if(!user.isModified('password')){
return next();
}
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if(err){
return next(err);
}
bcrypt.hash(user.password, salt, function(err, hash) {
if(err){
return next(err);
}
user.password = hash;
next();
});
});
});
Third argument must be callback function see document for bcrypt
I didn't (or haven't) find any problem with your code, but I have a suggestion to trace the bug.
This block of code is risky. You may accidentally update the password field and trigger the rehash password process.
UserSchema.pre('save', function(next) {
var user = this;
var SALT_FACTOR = 12; // 12 or more for better security
if (!user.isModified('password')) return next();
console.log(user.password) // Check accident password update
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
Put a console.log
right after the if (!user.isModified('password'))
to check for unexpected password update. Now retry forget the password and see if any bug in there.
*TD;LR Separate update password into a new method instead of putting it in the pre-save since you may accidentally update a new password along with other fields
*Update: Thanks #imns for suggesting a better SALT_FACTOR number.
I had the same issue just delete the null parameter from this line:
bcrypt.hash(user.password, salt, null, function(err, hash) {
I think the issue could be in the hash function. Tried duplicating you code into a simpler but similar experiment on my computer.
As the bcrypt docs state here https://www.npmjs.com/package/bcrypt#to-hash-a-password
The hash function only takes in 3 arguments, you send in 4. Whereas the third argument in your case is null.
Here is some code to illustrate the issue and the, hopefully, solution
Inside the salting callback
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
But change the third argument to be the callback function instead.
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});