I am trying to hash a password after updating it but I dont understand why it is just working after the await line. In the res.json I get the hashed password, but just there.
I am new to this so I appreciate any help or advice.
router.put('/:id', async (req, res) => {
let { mail, password } = req.body;
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) return next(err);
bcrypt.hash(password, salt, function (err, hash) {
if (err) return next(err);
password = hash;
});
});
const newUser = { mail, password };
await User.findByIdAndUpdate(req.params.id, newUser);
res.json({ mensaje: `Updated Password ${password}` });
});
As per my comment, you should look into async/await and callbacks more to understand the call order. As it's not running in the sequential fashion you think it is. But you can try the following.
router.put('/:id', async (req, res) => {
let { mail, password } = req.body;
try{
const salt = await bcrypt.genSalt(saltRounds);
const hashedPassword = await bcrypt.hash(password, salt);
const newUser = { mail, password };
await User.findByIdAndUpdate(req.params.id, newUser);
res.json({ mensaje: `Updated Password ${password}` });
} catch(error) {
res.json(error);
}
});
Related
this is the controller and if I do it whitout hashing it works but with hashing it give me an error and I cannot handle in catch(err)
this is the controller and if I do it whitout hashing it works but with hashing it give me an error and I cannot handle in catch(err)
this is the controller and if I do it whitout hashing it works but with hashing it give me an error and I cannot handle in catch(err)
const { throws } = require("assert");
const { bcrypt } = require("bcryptjs");
const User = require("../models/user");
// #desc register new user
// #routes POST /users/register
exports.createUser = async (req, res) => {
const errors = [];
try {
await User.userValidation(req.body);
const { fullname, email, password } = req.body;
const user = await User.findOne({ email });
if (user) {
errors.push({ message: "کاربری با این ایمیل موجود است" });
return res.render("register", {
pageTittle: "صحفه ثبت نام",
path: "/register",
errors: errors,
});
}
bcrypt.genSalt(10, (err, salt) => {
if (err) throw err;
console.log(err);
bcrypt.hash(password, salt, async (err, hash) => {
if (err) throw err;
await User.create({
fullname,
email,
password: hash,
});
res.redirect("/users/login");
});
});
} catch (err) {
err.inner.forEach((e) => {
errors.push({
name: e.path,
message: e.message,
});
});
}
return res.render("register", {
pageTittle: "صحفه ثبت نام",
path: "/register",
errors: errors,
});
};
I am experimenting with node authentication, I have managed to store a username and a hashed password into my database, but I want to return the json back without the hashed password.
I am deleting the password key before sending the JSON back but the password still shows in the returned result.
router.post("/signup", async (req, res, next) => {
const user = await User.exists({ username: req.body.username });
if (user) {
const error = new Error("Username already exists");
next(error);
} else {
const newUser = new User({
username: req.body.username,
password: req.body.password,
});
try {
const result = await newUser.save();
delete result.password;
res.json(result);
} catch (err) {
res.json(err.errors);
}
}
});
the User model has a pre hook to hash the password before save:
userSchema.pre("save", async function save(next) {
const user = this;
if (!user.isModified("password")) return next();
try {
user.password = await bcrypt.hash(user.password, 12);
return next();
} catch (err) {
return next(err);
}
});
Here is the solution thanks to Mahan for pointing it out.
result returns a Mongoose object so needs turning into a normal Javascript object first.
try {
let result = await newUser.save();
result = result.toObject();
delete result.password;
res.json(result);
} catch (err) {
res.json(err.errors);
}
I'm using bcrypt to authenticate the users in my system. When i register an user, with the code:
UserSchema.pre("save", async function(next) {
var user = this;
if (user.isModified('password')) {
var salt = bcrypt.genSaltSync(10);
await bcrypt.hash(user.password, salt, null, function(err, hash) {
if(err){
console.log(err);
}else {
user.password = hash;
}
});
}
next();
});
Ok, the hash is created and save in mongo. My problema is, when i log in with this user, any password works. Here's is my compare function:
UserSchema.methods.authenticate = async function(password) {
var user = this;
var isAuthenticaded = await bcrypt.compare(password, user.password,
function(err, res){
if(res){
return true;
}else{
return false;
}
});
return isAuthenticaded;
};
I call the function 'authenticate' with passport:
if (!user.authenticate(password)) {
return done(null, false, {message: 'Senha inválida.'});
}
Someone could help?
[EDIT] - I think the problem is asynchronous calls. Modified to syncrhonous and it works! I will apreciate if someone discover where is the problem with asyncrhonous calls
About async implementation.
UserSchema.pre('save', async function save(next) {
if (!this.isModified('password')) return next();
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
return next();
} catch (err) {
return next(err);
}
});
UserSchema.methods.authenticate = async function(password) {
return bcrypt.compare(password, this.password);
};
And now, if user using our async authentication method, we have to await for result.
if (!await user.authenticate(password)) {
return done(null, false, {message: 'Senha inválida.'});
}
You can read more about pre.
I have this route
router.patch("/me/update-password", authenticate, (req, res) =>{
let newPassword = _.pick(req.body, 'password');
const newP = newPassword.password;
User.findByCredentials(req.user.username, req.user.password).then((user) => {
user.password = newP;
user.save().then(() => {
res.send(user);
}).catch((e) => {
res.status(400).send(e);
});
});
});
/////////////////////////////////////////////////////////////////////////////
UserSchema.statics.findByCredentials = function (username, password) {
var User = this;
return User.findOne({username}).then((user) => {
if (!user) {
return Promise.reject();
}
return new Promise((resolve, reject) => {
// Use bcrypt.compare to compare password and user.password
bcrypt.compare(password, user.password, (err, res) => {
if (res) {
resolve(user);
} else {
reject();
}
});
});
});
};
//////////////////////////////////////////////////////////////////
UserSchema.pre('save', function (next) {
let user = this;
if (user.isModified('password')) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (err, hash) => {
user.password = hash;
next();
});
});
} else {
next();
}
});
I find the username and password of the authenticated user and then I want to send a new password which I save as newP.
I want to update the password hash and salt it and then save, so I tried with the method user.save() which hashes and salts the password. But when I send a patch request it wont`t finish.
Does anybody know why ?
I tried everything but I am stuck.
I am using Bcrypt for hashing passwords and storing it in the database,
Bcrypt is returning false, when I retrieve the hashed password from the database, and compare with the typed user password.
I am using it under Promise, but bcrypt is returning false on the correct password
Here is the code:
userSchema.statics.findByCredentials = function(email, password) {
const User = this;
return User.findOne({email}).then((user) => {
if(!user) {
return Promise.reject();
}
// console.log(user.password);
return new Promise((resolve, reject) => {
bcrypt.compare(password, user.password, (err,res) => {
if(res) {
resolve(user);
}
else {
reject("Problem here");
}
console.log(res);
});
});
});
};
I am trying promise chain to the main file i.e server.js and return the details to the user, but it's not working.
Here is the route code of express:
app.post('/users/login', (req, res) => {
const body = _.pick(req.body, ['email', 'password']);
// res.send(body);
User.findByCredentials(body.email, body.password)
.then((user) => {
res.send(user);
}).catch((e) => res.send(e));
});
Thanks
Have you tried using the promise api for bcrypt?
It might look like this:
userSchema.statics.findByCredentials = function(email, password) {
const User = this;
return User.findOne({email}).then((user) => {
if(!user) {
return Promise.reject();
}
// console.log(user.password);
return bcrypt.compare(password, user.password)
.then(res => {
if (res) {
return user;
}
throw new Error('Problem here');
});
});
}
If not, you might be getting an error, so you could check the err argument to see if something came back from there. Other than that, as long as user.password is the hashed version of the original password, then it should be working.