How to fix : " Error: data and hash arguments required " - mysql

I'm trying login with a user that I have registered in my form but I have this error:
Error: data and hash arguments required
The user is registered in my database with a Username, Fullname and the hashed password thanks to bcrypt.
const pool = require("./pool");
const bcrypt = require("bcrypt");
function User() {}
User.prototype = {
find: function(user = null, callback) {
if (user) {
var field = Number.isInteger(user) ? "id" : "username";
}
let sql = `SELECT * FROM users WHERE ${"" + field + ""} = ?`;
pool.query(sql, user, function(err, result) {
if (err) console.log(err);
callback(result);
});
},
create: function(body, callback) {
let pwd = body.password;
body.password = bcrypt.hashSync(pwd, 10);
var bind = [body.username, body.fullname, body.password];
console.log(bind);
let sql =
"INSERT INTO users(username, fullname, password) VALUES (?, ?, ?)";
pool.query(sql, bind, function(err, lastId) {
if (err) throw err;
callback(lastId);
});
},
login: function(username, password, callback) {
this.find(username, function(user) {
if (user) {
if (bcrypt.compareSync(password, user.password)) {
callback(user);
return;
}
}
});
}
};
module.exports = User;
Once i press my login button in my form this is the error I'm getting
throw err; // Rethrow non-MySQL errors
^
at Object.compareSync (/Users/me/happy/node_modules/bcrypt/bcrypt.js:167:15)
at /Users/me/happy/core/user.js:46:20
at Query.<anonymous> (/Users/me/happy/core/user.js:16:7)
at Query.<anonymous> (/Users/me/happy/node_modules/mysql/lib/Connection.js:525:10)
at Query._callback (/Users/me/happy/node_modules/mysql/lib/Connection.js:491:16)
at Query.Sequence.end (/Users/me/happy/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)
at Query._handleFinalResultPacket (/Users/me/happy/node_modules/mysql/lib/protocol/sequences/Query.js:139:8)
at Query.EofPacket (/Users/me/happy/node_modules/mysql/lib/protocol/sequences/Query.js:123:8)
at Protocol._parsePacket (/Users/me/happy/node_modules/mysql/lib/protocol/Protocol.js:291:23)
at Parser._parsePacket (/Users/me/happy/node_modules/mysql/lib/protocol/Parser.js:433:10)

Make sure you are passing valid values in both arguments. userpassword and dbpassword should not be undefined or null

Try to generate a salt synchronously, updating this line
body.password = bcrypt.hashSync(pwd, 10);
for
body.password = bcrypt.hashSync(pwd, bcrypt.genSaltSync(10));

Please check password and user.password is not equal to undefined. Because the same function is working fine for me.
If you are still facing the same issue then please try bcrypt.compare. bcrypt.compare takes 3 parameters passwordToCheck, passwordHash and a callback.
login: function(username, password, callback) {
this.find(username, function(user) {
if (user) {
bcrypt.compare(password, user.password, function(err, match) {
if (err) throw new Error(err);
else if (match == false) {
return res.json({
success: false,
message: 'Wrong Password'
})
} else {
callback(user);
return;
}
});
}
});
};

Related

bcrypt nodejs - null error when trying to login with comparing hashed password from the database

I created a basic register and login page connected to local mysql - that collects email, username and password (password gets hashed with bcrypt) and stores them in database.
Yet when i am trying to log in I get an error that says just : null + (console log saying password + else2 so i know which line got called)
This is login.js file
exports.login = (req, res) => {
console.log(req.body);
let email = req.body.email;
let password = req.body.password;
let username = req.body.username;
//if it finds username and email matching login credentials it will check for password
db.query('SELECT username, email, password FROM users WHERE username = ? AND email = ?', [username, email], function (error, results) {
if (error) {
res.send({
"code": 400,
"failed": "error ocurred"
});
}
//results[0].password means the password of the user that was found.
// it should compare plain password with the encrypted password in database
//and redirect to the /profile page if the password are a match.
if (results.length > 0) {
bcrypt.compare(password, results[0].password, function (error, answer) {
if (error) {
console.log(password +'if1')
console.log("comparing gone wrong", error);
return res.render('login', {
message3: 'Comparing error - please try again later'
});
}
if (answer) {
console.log(password + 'if 2')
res.redirect("/profile");
console.log("login successfull!");
}
else {
console.log(password + ' else2', error)
return res.render('login', {
message3: 'User or password or email is wrong'
});
}
});
} else {
console.log(password + 'else3')
return res.render('login', {
message3: 'User or password or email is wrong'
});
}
});
};
I will also put the register.js file if that will help with anything.
exports.register = (req, res) => {
console.log(req.body);
const { username, email, password, passwordConfirm } = req.body;
db.query('SELECT email FROM users WHERE email = ?', [email], async (error, result) => {
if(error) {
console.log(error);
}
if( result.length > 0 ) {
return res.render('register', {
message: 'That email is already in use'
})
} else if( password !== passwordConfirm) {
return res.render('register', {
message: 'That passwords do not match'
});
}
let hashedPassword = await bcrypt.hash(password, 8);
console.log(hashedPassword);
db.query('INSERT INTO users SET ?', {username: username, email: email, password: hashedPassword }, (error, result) => {
if(error) {
console.log(error);
} else {
console.log(result);
return res.render('register', {
message2: 'User Registered!'
});
}
})
});
}
Well, now I know why finding an answer online was so hard.
The code is right, the problem was in my database, I previously allowed for 50 Varchar password (but hashing it makes it longer, and it was getting cut), after I changed it to 128 chars it works perfectly with the new users that now register and login under the new broader restrictions.

Retrieve information upon registration

How can i do this, When a user registers , I would like the endpoint to still go ahead and get back the information which is saved inside the database.For some reason, it does not work as expected
How do i go about this :
My code is looking thus :
app.post("/api/sign-up", async function (req, res) {
dbConn.query(
`select * from accounts where email = ${dbConn.escape(req.body.email)}`,
async function (err, result, fields) {
if (result.length === 0) {
var email = req.body.email;
var phone = req.body.phone;
var password = req.body.password;
var fullname = "NULL";
const hashPass = await bcrypt.hash(password, 12);
dbConn.query(
`insert into accounts(email, phone, password, fullname) values (?,?,?,?)`,
[email, phone, hashPass, fullname],
function (error, results, fields) {
if (error) throw error;
return res.send({
error: false,
data: results[0],
message: "User created Successfully",
});
}
);
} else {
return res.send({
error: true,
message: "User exists",
});
}
}
);
});
Checked thru the internet, i could not find the information needed.
I managed to fix it.
Code looks like this now , and it shows the data inside POST man
app.post("/api/sign-up", async function (req, res) {
dbConn.query(
`select * from accounts where email = ${dbConn.escape(req.body.email)}`,
async function (err, result, fields) {
if (result.length === 0) {
var email = req.body.email;
var phone = req.body.phone;
var password = req.body.password;
var fullname = "NULL";
const hashPass = await bcrypt.hash(password, 12);
dbConn.query(
`insert into accounts(email, phone, password, fullname) values (?,?,?,?)`,
[email, phone, hashPass, fullname],
function (error, results, fields) {
if (error) throw error;
return res.send({
error: false,
email:email,phone:phone,
message: "User created Successfully",
});
//return res.status(201).json({message: 'User created Successfully', "email":email,"phone":phone});
}
);
} else {
return res.send({
error: true,
message: "User exists",
});
}
}
);
});
Thanks to everyone who decided to take a Look :)

TypeError : res.status is not a function returning Login message and Token

i am getting this as error
TypeError : res.status is not a function
I do not know why, but i am getting this Error
My code is looking thus :
app.post('/api/v1/user/login', async function(req,res){
var email = req.body.email;
var password = req.body.password;
dbConn.query(`SELECT * FROM XXXXXXXXX_users WHERE email = ${dbConn.escape(req.body.email)};`,(err,result)=>{
if(err){
throw err;
return res.status(400).send({message: err,})
}
if(!result.length){
return res.status(400).send({message: 'Username and password incorrect!',})
}
bcrypt.compare(req.body.password,result[0]['password'],(err,res)=>{
if(err){
throw err;
return res.status(400).send({message: 'Username and password Incorrect!'});
}
if(result){
const token = jwt.sign({email: result[0].email,id:result[0].id},'the-super-strong-secrect',{ expiresIn: '1h' });
return res.status(200).send({message: 'OK', token}) // Error is here
}
return res.status(400).send({message: 'User and pass incorrect'})
})
})
})
I am trying to implement Login system backend API please I would like to know why this is not working as its supposed to. Kindly help. A bit new to this
Issue is in this line
bcrypt.compare(req.body.password,result[0]['password'],(err,res) //<-- Using res keyword here
See how you are using (err, res) for this callback. This interferes with
app.post('/api/v1/user/login', async function(req,res) //<-- Also using res keyword here
I would suggest you to use async/await for better cleanup.
app.post('/api/v1/user/login', async function(req, res) {
let email = req.body.email;
let password = req.body.password;
try {
const queryResult = await dbConn.query(`SELECT * FROM XXXXXXXXX_users WHERE email = ${dbConn.escape(req.body.email)};`)
if (!queryResult.length) {
return res.status(400).send({
message: 'Username and password incorrect!',
})
}
const compareResult = await bcrypt.compare(req.body.password, queryResult[0]['password'])
if (compareResult) {
const token = jwt.sign({
email: queryResult[0].email,
id: queryResult[0].id
}, 'the-super-strong-secrect', {
expiresIn: '1h'
});
return res.status(200).send({
message: 'OK',
token
})
}
return res.status(400).send({
message: 'User and pass incorrect'
})
}
catch (err) {
res.status(500).json({
err
});
}

TypeError: Cannot read property 'password' of undefined in login route

When i'm requesting the api with the email which does not exist in the mysql DB it throws a error but in the opposite condition it runs.
Error:
S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\Parser.js:437
throw err; // Rethrow non-MySQL errors
^
TypeError: Cannot read property 'password' of undefined
at Query.db.query (S:\#development\Pepperkart\pepperkart-backend\routes\users.js:19:43)
at Query.<anonymous> (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\Connection.js:525:10)
at Query._callback (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\Connection.js:491:16)
at Query.Sequence.end (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query._handleFinalResultPacket (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\sequences\Query.js:139:8)
at Query.EofPacket (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\sequences\Query.js:123:8)
at Protocol._parsePacket (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\Protocol.js:291:23)
at Parser._parsePacket (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\Parser.js:433:10)
at Parser.write (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\Parser.js:43:10)
at Protocol.write (S:\#development\Pepperkart\pepperkart-backend\node_modules\mysql\lib\protocol\Protocol.js:38:16)
[nodemon] app crashed - waiting for file changes before starting...
My api looks like this:
router.post('/login', (req, res) => {
var email = req.body.email
var password = req.body.password
var GRAB_USER = `SELECT * FROM user_details WHERE email = ?`
db.query(GRAB_USER, email, (err, result) => {
if (err) {
res.send('email not found')
} else {
var user = result[0]
bcrypt.compare(password, user.password, (err, match) => {
if (err) {
res.send('password not match')
} else {
res.send(user)
}
});
}
})
})
your query is fine and not giving error so you should also check result.length> 0 and then res.send('email not found')
router.post('/login', (req, res) => {
var email = req.body.email
var password = req.body.password
var GRAB_USER = `SELECT * FROM user_details WHERE email = ?`
db.query(GRAB_USER, email, (err, result) => {
if (err) {
res.send('email not found')
}
else if (result.length==0) {
res.send('email not found') //this is what you are missing
}
else {
var user = result[0]
bcrypt.compare(password, user.password, (err, match) => {
if (err) {
res.send('password not match')
} else {
res.send(user)
}
});
}
})
})
after the following line of code, I would recommend to add a console statement and see what are you getting in user because your user is undefined here
var user = result[0]
console.log(user)
and see the result if the user is undefined and add a console for result and see what are you getting in result then assign the value in user

Node.js - Express & mysql TypeError: res.json is not a function although insert is successful

Although I have a successful insert I get an error (TypeError: res.json is not a function) when I want to return a json message upon. This is my setup:
const express = require('express');
module.exports = {
signup: async (req, res, next) => {
const { email, username, password } = req.value.body;
const connection = require('../config/dbconnection');
connection.query("SELECT * FROM tbl_users WHERE email = ?",[email], function(err, rows) {
if (rows.length) {
return res.json({ err: 'Email already exist'});
} else {
var newUserMysql = {
email: email,
username: username,
password: password
};
var insertQuery = "INSERT INTO tbl_users ( email, username, password ) values (?,?,?)";
connection.query(insertQuery,[newUserMysql.email, newUserMysql.username, newUserMysql.password],function(err, res, rows) {
if(err){
console.log('Insert error');
//res.json({ err: 'Insert error'});
} else {
console.log('Insert successful');
return res.json({ 'success': 'Insert successful'});
//return done(null, newUserMysql);
}
});
}
});
}
How can I return a json on successfull insert?
Your function's res parameter is hidden by the res return value from the connection.query call.
Rename the res parameter of this call to result (for example) and you should be fine:
connection.query(insertQuery,[newUserMysql.email, newUserMysql.username, newUserMysql.password],function(err, result, rows) {
if(err){
console.log('Insert error');
//res.json({ err: 'Insert error'});
} else {
console.log('Insert successful');
return res.json({ 'success': 'Insert successful'});
//return done(null, newUserMysql);
}
});
When you have nested scopes with conflicting variable names, the variable the closest (scope-wise) from where you reference this conflicting name will be used.
You're redefining res in your connection.query(insertQuery, [.....], function(err, res, rows) { ...}) function.
That res overrules the res from your express router within the scope of that function