I'm currently trying to implement a password reset service with NodeJS using Bcrypt. I've created a hash of an object like this:
const userData = {
dateNow,
userId: foundUser.rows[0].user_id,
passwordHash: foundUser.rows[0].user_password,
email: foundUser.rows[0].user_email
};
const userDataHash = await hashUserData(userData, 10);
Where userDataHash is:
const hashUserData = async (userData, saltRounds) => {
let hashedData = await bcrypt.hash(JSON.stringify(userData), saltRounds);
if (hashedData.includes('/') || hashedData.includes('.')) {
hashedData = hashUserData(userData, saltRounds);
}
console.log('hashUserData', hashedData)
return hashedData;
};
The hashing function is a bit hacky as because it forms part of the reset URL I don't want any hashes with / or .
The hash of the user data object is then added to a URL. When the user clicks the link and is taken to the password reset, when they submit the form the hash from the URL is sent along with the user ID of the account to reset, this ID is then used to create an object of the same data originally used to create the hash, so that if the password hash has already been changed then the hash will not match, stopping the person from updating their password.
My issue is that even when the password hash changes, the hash comparison returns true. If I change anything else in the object, the hash comparison returns false.
const compareHash = async (toCompare, currentHash) => {
return await bcrypt.compare(toCompare, currentHash)
};
const userDataToCheck = {
dateNow: req.params.dateNow,
userId,
passwordHash: foundUser.rows[0].user_password,
email: foundUser.rows[0].user_email
};
const hashesMatch = await compareHash(JSON.stringify(userDataToCheck), req.params.userDataHash)
Where req.params.userDataHash is the original hash using the original password hash in the object.
Any help appreciated!