I am working on a login script with Node.js and using bcrpyt to compare password hashes. When using the bcrpyt library, the compare function fails. However when I use the bcrpytjs library, the compare function succeeds. Below is the login function. I've included the hash and password for use is testing.
Password: LHLiiSGd1xLg
Hash: $2y$10$J47x5GEFtmULWem2nh3YvuZaAiZyFZlyTUFV97dAx2.dyb8Yst43y
function login(email, password, callback) {
// Require depedencies
const bcrypt = require("bcrypt")
const mysql = require('mysql');
// Create our mysql connection
const connection = mysql.createConnection({
host: configuration.host,
user: configuration.user,
password: configuration.password,
database: configuration.database
});
// Connect to the database
connection.connect();
// Create the database query
const query = 'SELECT id, firstname, lastname, email, password FROM tblclients WHERE email = ?';
// Query the database
connection.query(query, [ email ], function(err, results) {
// If we have an error
if (err) return callback(err);
// If we have no results
if (results.length === 0) return callback(new WrongUsernameOrPasswordError(email));
// Define the user object
const user = results[0];
console.log('Query: ', results);
// Compare the two hashes
bcrypt.compare(password, user.password.toString(), function(err, isMatch) {
// If the passwords do not match
if (err) return callback(err);
if (!isMatch) return callback('Passwords do not match');
// Return the user
callback(null, {
user_id: user.id.toString(),
nickname: user.firstname + ' ' + user.lastname,
email: user.email
});
});
});
}
I replaced the 2y prefix with 2a and the function now correctly works.
user.password.toString().replace(/^\$2y/, "$2a")
Related
I am currently making a webapp with a database using express and postgres and am having trouble implementing registration.
This is a small snippet of what happens after the user keys in username, name and password into a form which is then posted to the '/registerUser' route. Here is the post request at the '/registerUser' route. The pool.query works for the check_username, however, is does not work for the add_user query.
Here are the 2 queries:
check_username = 'SELECT 1 FROM Users where username = $1'
add_user = 'INSERT INTO users VALUES (username, name, password) VALUES ($1, $2, $3)'
router.post('/', function(req, res, next) {
var name = req.body.name;
var username = req.body.username;
var password = req.body.password;
pool.query(sql_query.query.check_username, [username], (err, data) =>{
if(data.rows[0] != undefined) {
console.log(`re register again!`);
res.redirect('/registerUser');
} else {
console.log("adding to database")
// Generate salt
bcrypt.genSalt(10, (err, salt) =>{
if(err) {
console.log(err);
}
// hash it with salt
bcrypt.hash(password, salt, (err,hash)=>{
if(err) console.log(err)
//password = hash
console.log(`${username} + ${password}`);
// save to database
pool.query(sql_query.query.add_user, [name, username, password], (err, data) => {
console.log("pass")
res.redirect("/")
});
});
});
}
});
});
What exactly is the problem here? Could it be that i cannot nest pool.queries?
the answer is that there is a syntax error with the insert queries. There shouldnt be a VALUES in front of the table columns.
I am writing code in Node.js to encrypt passwords using bcrypt.
However, if you use bcrypt, you will get an ValidationError: User validation failed: password: Cast to String failed for value "Promise { <pending> }" at path "password"
I do not get this error if I save it as plain text without encryption.
Is there a secret of bcrypt I do not know?
bcrypt (not working)
const bcrypt = require('bcrypt');
sign_up = (req, res, next) => {
const { email, password } = req.body;
const User = User.findOne({ email: email });
if (exUser) {
return res.send('exist user');
}
const hash = bcrypt.hash(password, 8);
const user = new User({
email: email,
password: hash
});
user.save((err) => {
if (err) {
return next(err);
}
res.send('signup success');
});
};
no bcrypt (working)
sign_up = (req, res, next) => {
const { email, password } = req.body;
const User = User.findOne({ email: email });
if (exUser) {
return res.send('exist user');
}
const user = new User({
email: email,
password: password
});
user.save((err) => {
if (err) {
return next(err);
}
res.send('signup success');
});
};
To elaborate on Chris's comment:
It appears that bcrypt.hash is asynchronous, and is returning a Promise.
To fix this, I would recommend using an async function and awaiting the result. MDN page
This may require a newer version of NodeJS than what you are running.
const bcrypt = require('bcrypt');
// Async function allows us to use await
sign_up = async (req, res, next) => {
const { email, password } = req.body;
const User = User.findOne({ email: email });
if (exUser) {
return res.send('exist user');
}
// We await the result of the hash function
const hash = await bcrypt.hash(password, 8);
const user = new User({
email: email,
password: hash
});
user.save((err) => {
if (err) {
return next(err);
}
res.send('signup success');
});
};
Do not use the bcrypt.hashSync function, as while it is running your server will not be able to do anything else.
I've seen this asked before but in other languages (C# and PHP) but I am working through Javascript. I am storing a username and password onto my database but the password is being hashed via bcrypt.
I can store it correctly but I cannot pull it from my database and compare it correctly. It always console logs my 'password does not match' message.
This is my registration code that stores the username and password onto my database.
app.post('/register', function (req, res) {
var usernameCollection = mongoDBDatabase.collection('accounts');
username = req.body.username;
bcrypt.hash(req.body.password, saltRounds, function (err, hash) {
usernameCollection.insertOne({
personId: req.body.username,
username: req.body.username,
password: hash
}).then(function(data) {
if (data) {
//res.redirect('/' + username);
//window.location.href = "/" + username;
}
});
});
});
And here is my code where I am searching my database for the username and trying to compare the password to no avail.
//login page: storing and comparing email and password,and redirecting to home page after login
app.post('/login', function (req, res) {
var usernameCollection = mongoDBDatabase.collection('accounts');
var username = req.body.username;
var enteredPassword = req.body.password;
usernameCollection.findOne({
$or:[
{ username: username}
]
}).then(function(user){
if (user) {
console.log('That username was found in the database');
bcrypt.compare(enteredPassword, user.password, function(err, result){
if(result == true){
console.log('Password matches!');
res.redirect('/' + username);
}
else{
console.log('Password did not match');
res.redirect('/');
}
});
}
else{
console.log('The username ' + username + ' was NOT found in the database');
}
});
});
I just want to compare the stored password to the entered password and confirm they are the same to log the user in.
I am using Koa module - Node js and mysql & stuck on a problem.
In signup function (inside welcomeCtrl.js) I have:
var bcrypt = require('bcrypt');
module.exports = {
signup: function* (next) {
bcrypt.genSalt(10, function(err, salt) {
console.log(salt);
bcrypt.hash(password, salt, function(err, hash) {
// Store hash in your password DB.
console.log(hash); //no error
var hashedPassword = hash;
});
});
console.log(bcrypt.hash.hash); //gives error
//or
console.log(bcrypt.hash.hahedPassword); //gives error
queryString = "insert into user(email,name, phone, password, course_id, dpt_id) values('%s','%s','%s','%s','%s','%s')";
query = util.format(queryString, email, name, phone, hash, courseId, dptId);
results = yield databaseUtils.executeQuery(query);
this.redirect('/');
}
}
I am calling signup post function in different routes.js file as:
router.post('/signup', welcomeCtrl.signup);
Here is the executeQuery function in the databaseUtils.js file
var executeQuery = function(query, callback) {
pool.getConnection(function(err, connection) {
// Use the connection
connection.query(query, function(err, rows, fields) {
connection.release();
if(err) {
err.mysqlQuery = query;
logger.logError(err);
}
if(typeof callback == "function") {
callback(err, rows);
}
// Don't use the connection here, it has been returned to the pool.
});
});
};
module.exports = {
executeQuery: thunkify(executeQuery),
executePlainQuery: executeQuery
};
Is there any way to use hash variable outside the function so that it can be inserted in query?
You should move your query function into the callback for bcrypt.hash.
bcrypt.genSalt(10, function(err, salt) {
console.log(salt);
bcrypt.hash(password, salt, function(err, hash) {
// Store hash in your password DB.
console.log(hash); //no error
queryString = "insert into user(email,name, phone, password, course_id, dpt_id) values('%s','%s','%s','%s','%s','%s')";
query = util.format(queryString, email, name, phone, hash, courseId, dptId);
databaseUtils.executeQuery(query, function() {
this.redirect('/');
});
});
});
Problem is, where does your redirect function come from? You're going to loose context on this unless you bind the functions. Do fat arrow functions work in your setup? If so you could do it that way.
1st post. I'm a student studying js and came across this problem with a callback that I'm not sure how to structure properly.
var bcrypt = require('bcrypt-nodejs');
var users = db.collection("users");
this.addUser = function(username, password, email, callback) {
"use strict";
// Generate password hash
var salt = bcrypt.genSaltSync();
var password_hash = bcrypt.hashSync(password, salt);
// Create user document
var user = {'_id': username, 'password': password_hash};
// Add email if set
if (email != "") {
user['email'] = email;
}
// NOT SURE What to write here
callback(Error("addUser Not Yet Implemented!"), null);
}
First of all: do not use sync methods if possible, use callbacks instead.
var bcrypt = require('bcrypt-nodejs');
var users = db.collection("users");
this.addUser = function(username, password, email, callback) {
"use strict";
// Generate password hash
bcrypt.genSalt(function(err, salt) {
if (err) {
callback(err);
return;
}
bcrypt.hash(password, salt, function(err, password_hash) {
if (err) {
callback(err);
return;
}
// Create user document
var user = {
'_id': username,
'password': password_hash
};
// Add email if set
if (email != "") {
user['email'] = email;
}
// NOT SURE What to write here
callback(null);
});
});
}
and please ask precise questions.
If I understand propperly, you dont know how to handle a callback?
you simply pass the function that will be called after all work in your function is done as the parameter callback. when your done, you call the callback with the wanted parameters.
here it's the err object in case of an error or null if there is no error.
If you want to pass your created user to the callback, just replace
callback(null); with callback(null, user);