Change Password Get Request Not Changing Password - node.js

I have a MEAN application that is trying to implement a GET Request for '/changepassword'. This file is located in '/users/changepassword'. I am using Mongoose and bcryptjs for my password hashing. Please take a look at my code below.
This is /users/changepassword
// Change Password
router.post('/changepassword', function(req, res){
var username = req.body.username;
var password = req.body.oldPassword;
var newPassword = req.body.newPassword;
User.getUserByUserName(username, function(err, user){
if(err) throw err;
if(user === null){
res.json({success: false, msg: "The given username does not exist."});
}else{
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch)
{
User.changePassword(user, newPassword,function(err, changedPassword){
if(err) throw err;
else{
if(changedPassword === true){
res.json({success: true, msg: "Your password has been changed."});
}
else {
res.json({success: false, msg: "Your password was unable to be changed."});
}
}
});
}
});
}
});
});
This is the Mongoose changepassword function located in /models/user
module.exports.changePassword = function(user, newPassword, callback){
var query = {username: user.username};
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(user.password, salt, function(err, hash){
if (err) throw err;
else{
user.password = hash;
User.findOneAndUpdate(query, { $set: { password: user.password }}, {new: true}, function(err, newUser){
if(err) throw err;
else{
bcrypt.compare(newPassword, newUser.password, function(err, isMatch){
if(err) throw err;
console.log(isMatch);
callback(null, isMatch);
});
}
});
}
});
});
};
Here are all other functions used in the /models/user
module.exports.getUserByUserName = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
};
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch){
if(err) throw err;
callback(null, isMatch);
});
};
When I use postman, this is the output I receive
{
"success": false,
"msg": "Your password was unable to be changed."
}
Any help is much appreciated! :)

Found out what was wrong!
module.exports.changePassword = function(user, newPassword, callback){
var query = {username: user.username};
bcrypt.genSalt(10, function(err, salt){
// it has to be newPassword instead of user.password
bcrypt.hash(user.password, salt, function(err, hash){
if (err) throw err;
else{
user.password = hash;
User.findOneAndUpdate(query, { $set: { password: user.password }}, {new: true}, function(err, newUser){
if(err) throw err;
else{
bcrypt.compare(newPassword, newUser.password, function(err, isMatch){
if(err) throw err;
console.log(isMatch);
callback(null, isMatch);
});
}
});
}
});
});
};
// CORRECT ONE
module.exports.changePassword = function(user, newPassword, callback){
var query = {username: user.username};
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newPassword, salt, function(err, hash){
if (err) throw err;
else{
user.password = hash;
User.findOneAndUpdate(query, { $set: { password: user.password }}, {new: true}, function(err, newUser){
if(err) throw err;
else{
bcrypt.compare(newPassword, newUser.password, function(err, isMatch){
if(err) throw err;
console.log(isMatch);
callback(null, isMatch);
});
}
});
}
});
});
};

Related

Node App Crashes Due to Empty String as a Password

The application works fine if the username or the password is incorrect.
But crashes if the username entered is correct and no password is entered.
This is the Error I'm getting before the app crashes:
Error: Illegal
arguments: undefined, string at _async
user.js
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, (err, isMatch) =>{
if(err) throw err;
callback(null, isMatch);
});
}
users.js:
router.post('/authenticate/user', (req, res, next) =>{
const username = req.body.username;
const password = req.body.password;
User.getUserByUsername(username, (err, user) => {
if(err) throw err;
if(!user){
return res.json({success: false, msg: 'User Not Registered'});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch){
const token = jwt.sign({data: user}, config.secret, {
expiresIn : '6h'
});
res.json({
success: true,
token: 'JWT ' +token,
user:{
id: user._id,
username : user.username
}
});
} else {
return res.json({success: false, msg: 'Wrong Password'});
}
});
});
});
Should I add validation on the front-end of the application for a quick fix or is that not a good idea?
Thanks in advance.
Simple fix would be to check "candidatePassword" before comparing to hash and if it is empty throw an error.

Node.js hash updated password

Well, i have simple user edit in node,express,mongodb. But i am unable to hash password to bcrypt. In registration works everything allright but that was tutorial...
Here is part of my routes/users.js
Everything is updated but password is not hashed and i dont know what to do.
router.post("/profile", function (req, res) {
let user = {};
user.firstname = req.body.firstname;
user.lastname = req.body.lastname;
user.email = req.body.email;
user.password = req.body.password;
user.password2 = req.body.password2;
req.checkBody("firstname", "Firstname is required").notEmpty();
req.checkBody("lastname", "Lastname is required").notEmpty();
req.checkBody("email", "Email is required").notEmpty();
req.checkBody("email", "Email is not valid").isEmail();
req.checkBody("password", "Password is required").notEmpty();
req
.checkBody("password", "Password must be longer then 8 chars bitch")
.len(8, 64);
req
.checkBody("password2", "Passwords do not match")
.equals(req.body.password);
var errors = req.validationErrors();
if (errors) {
res.render("profile", {
errors: errors
});
} else {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(user.password, salt, function(err, hash) {
user.password = hash;
});
});
let query = {_id:req.user.id}
User.update(query, user, function(err){
if(err){
console.log(err);
return;
} else {
res.redirect('/');
}
});
}});
Here is my hasing for registration in models/users.js that i was inspired by.
module.exports.createUser = function(newUser, callback) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
};
I will be thankfull for any help.
Well after hous its solved.
I just changed it to.
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(user.password, salt, function(err, hash) {
user.password = hash;
let query = {_id:req.user.id}
User.update(query, user, function(err){
if(err){
console.log(err);
return;
} else {
res.redirect('/');
}
});
});
});
}});

bcryptjs comparePassword always returns false - NodeJS

I have looked at the other answers to the question on here but still not getting anywhere. I cannot get the comparePassword function to return true
module.exports.createUser = function(newUser, callback) {
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newUser.password, salt, function(err, hash){
newUser.password = salt;
newUser.save(callback);
});
});
};
module.exports.comparePassword = function(candidatePassword, hash, callback){
console.log("Provided password is " + candidatePassword);
console.log("Provided hash is " + hash);
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
console.log(isMatch);
callback(null, isMatch);
});
}
So if we take the user in test at this stage you can see their data
{ _id: 5aec6f702a4a181f261a43fe,
full_name: 'Its me',
username: 'myusername',
email: 'myemail#gmail.com',
tel_number: '12345678',
password: '$2a$10$6GCgZDt.FL/eeZ1NsDASe.', // text version = test
__v: 0
}
When comparePassword is run the console logs return
Provided password is test
Provided hash is $2a$10$6GCgZDt.FL/eeZ1NsDASe.
So to me they match right?
Not sure what is going on here.
Could you try replacing the line newUser.password = salt; with newUser.password = hash; ?
And let us know if that works.
I have an example in my github repo, it might help
https://github.com/shirshendubhowmick/jwt-demo
Here is a snippet of the code from the repo
bcrypt.genSalt(10, (error, salt) => {
bcrypt.hash(user.password, salt, (error, hash) => {
user.password = hash;
next();
});
});

mongoose password gets hashed twice

I am new to Mongoose and Node JS, and have this problem with password being hashed again after a user is updated.
Here is the code for hashing:
UserSchema.pre('save', function (next) {
var user = this;
bcrypt.hash(user.password, 10, function (err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
})
});
and this is for updating the user
router.post('/insert', function (req, res) {
User.findById(req.session.userId, function (err, user) {
if (err) { throw err; }
if (user) {
user.patients = req.body.patients
user.diagnosis_list = req.body.diagnosis_list
user.medicine_dose_list = req.body.medicine_dose_list
user.medicine_list = req.body.medicine_list
user.save(function (err) {
if (err) throw err;
res.send(user.toJSON());
})
}
})
})
I understand that presave has to be prevented to be called on updating the user, I just have no clue how to do that. Is there some other way I can update the user without having presave being called maybe?
if (!user.isModified('password')) {
return next();
}
bcrypt.hash(user.password, 10, function (err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
})
http://mongoosejs.com/docs/api.html#document_Document-isModified

Attaching method to schema in Node not being called

I am using a password verification based on this demo http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt and for some reason the method is not attaching to my 'user' return, resulting in an error
Here is my code...
module.exports = function (app, mongoose, config, passport) {
var bcrypt = require('bcrypt')
var SALT_WORK_FACTOR = 10;
var UserSchema = new mongoose.Schema({
name: { type: String },
password: { type: String, required: true },
email: {
type:String,
lowercase: true,
required: true,
unique: true
}
});
var _User = mongoose.model('user', UserSchema);
// Bcrypt middleware
UserSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_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();
});
});
});
// Password verification
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if(err) return cb(err);
cb(null, isMatch);
});
};
return {
User : _User,
isValidUserPassword : function(auth, done) {
_User.findOne({email : auth.body.username}, function(err, user){
// if(err) throw err;
if(err) return done(err);
if(!user) return done(null, false, { message : 'Incorrect email.' });
user.comparePassword(auth.body.password, function(err, isMatch) {
if (err) throw err;
console.log('Password123:', isMatch); // -> Password123: true
});
});
}
}
}
The problem with your code is that it calls
var _User = mongoose.model('user', UserSchema);
before defining the UserSchema.pre hook and UserSchema.methods.comparePassword method.
Call mongoose.model after defining your schema and things will work:
// Bcrypt middleware
UserSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_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();
});
});
});
// Password verification
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if(err) return cb(err);
cb(null, isMatch);
});
};
var _User = mongoose.model('user', UserSchema);

Resources