How to select rows[0] while inserting in node-mysql? - mysql

I'm fairly new to nodejs and callbacks. Here is my problem, using passportJS's LocalStrategy and node-mysql :
exports.register = new LocalStrategy(strategyOptionsRegister, function(req, username, password, done) {
//get data from the request
var data = {
username: username,
email: req.body.email,
password: password
};
console.log('data : ', data);
//Hash passwords
bcrypt.genSalt(10, function(err, salt) {
if (err) return next(err);
bcrypt.hash(password, salt, null, function(err, hash) {
// Store hash in your password DB.
if (err) return next(err);
data.password = hash;
//insertion
connection.query('INSERT INTO USERS SET ?', data, function(err, rows) {
if (err) {
console.log(err);
return next("Mysql error, check your query");
}
return done(null, rows[0]);
});
});
});
});
I'm trying to return rows[0] containing all the data, but i don't know how should i implement the SELECT command ? Is it before or after the callback for the insertion ? For the moment, rows[0] is naturally undefined.

what about using async.waterfall?
I solve similar problem.
insert query
get auto_incremnet number from rows[0]
select query
website of async here
https://github.com/caolan/async#waterfall
Also, as bcrypt is asyncronous,
data,password = hash
this code doesn't work properly.
I want to execute same type of code for yours but I can't.
So, I use bcrypt in Sync and pass the hash to query.

Here is my solution :
exports.register = new LocalStrategy(strategyOptionsRegister, function(req, username, password, done) {
//get data from the request
var data = {
username: username,
email: req.body.email,
password: password
};
//Hash passwords
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return done(err);
}
// Store hash in your password DB.
bcrypt.hash(password, salt, null, function(err, hash) {
if (err) {
return done(err);
}
data.password = hash;
//insertion
connection.query('INSERT INTO USERS SET ?', data, function(err, rows) {
if (err) {
return done(null, false, {
message: 'Mysql error, check your query !'
});
}
// to return all the info in rows[0]
connection.query('SELECT * FROM USERS WHERE email = ?', data.email, function(err, rows) {
if (err) {
return done(null, false, {
message: 'Email not found !'
});
}
return done(null, rows[0]);
});
});
});
});
});

Related

User always getting failure redirected using passport?

No matter what I change the user login will keep redirecting to failure instead of success. I don't know if I'm missing something or if I did something wrong. I tried to read the documentation for passport but, I found it pretty confusing. Here is my github link if you need to see the rest of the code. The node files are in app.js and passport-config.js.The sign up part of the website is working. https://github.com/gego144/to-do-list-website/tree/main
const customFields = {
usernameField: 'email',
passwordField: 'password'
}
const verifyCallback = (username, password, done) => {
user_exists = userName_Checker(username), function (err, user) {
if (err) { return done(err); }
if (userName_Checker(username) == false) {
console.log('wrong user');
return done(null, false, { message: 'Incorrect username.' });
}
if (password_finder(username, password)) {
console.log('wrong pass');
return done(null, false, { message: 'Incorrect password.' });
}
console.log('wtf');
return done(null, user);
};
;
}
const strategy = new LocalStrategy(customFields, verifyCallback);
passport.use(strategy);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// function that checks to see if the users email is in the database
function userName_Checker(email_name){
var sql = "select * from info where email = ?";
var user_email = [[email_name]];
db.query(sql, [user_email],function (err,result){
if (err) throw err;
var not_unique = result.length;
if(not_unique == 0){
return false;
}
else{
return true;
}
}
)}
// function that checks to see if the password in the database matches with the email
function password_finder(email_name, pass){
var sql = "SELECT password FROM info WHERE email = ?";
var user_email = [[email_name]];
db.query(sql, [user_email],function (err,result){
if (err) throw err;
bcrypt.compare(result, pass, function(err, res){
if(err){ throw err};
if(res){
return true;
}
else{
return false;
}
})
}
)}
My post method in my other file.
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect:'/index.html',
failureFlash: true
}))
Edit 1.
I just want to mention that the console.logs you see in verify Callback all don't log anything for some reason too.
The problem might be in the serialization logic.
In passport.serializeUser, you are passing in the whole user object, but when deserializing you are passing the id
Though I am not using SQL, the logic should be similar.
So the code should be something like this:
// Session
// Pass in user id => keep the session data small
passport.serializeUser((id, done) => {
done(null, id);
});
// Deserialize when needed by querying the DB for full user details
passport.deserializeUser(async (id, done) => {
try {
const user = await User_DB.findById(id);
done(null, user);
} catch (err) {
console.error(`Error Deserializing User: ${id}: ${err}`);
}
});
// Export the passport module
module.exports = (passport) => {
passport.use(new LocalStrategy({ usernameField: 'email', }, async (email, password, done) => {
try {
// Lookup the user
const userData = await User_DB.findOne({ email: email, }, {
password: 1, }); // Return the password hash only instead of the whole user object
// If the user does not exist
if (!userData) {
return done(null, false);
}
// Hash the password and compare it to the hash in the database
const passMatch = await bcrypt.compare(password, userData.password);
// If the password hash does not match
if (!passMatch) {
return done(null, false);
}
// Otherwise return the user id
return done(null, userData.id);
} catch (err) {
passLog.error(`Login Error: ${err}`);
}
}));
};
These options for passport seems to malfunction a lot or exhibit weird behaviors, so I suggest you handle the redirection logic like in my controller.
{ successRedirect: '/good',
failureRedirect: '/bad' }
Login controller logic:
(I am omitting the code here for session storage and made some modifications, but this code should work for what you need)
const login = (req, res, next) => {
//Using passport-local
passport.authenticate('local', async (err, user) => {
//If user object does not exist => login failed
if (!user) { return res.redirect('/unauthorized'); }
//If all good, log the dude in
req.logIn(user, (err) => {
if (err) { return res.status(401).json({ msg: 'Login Error', }); }
// Send response to the frontend
return res.redirect('/good');
});
});
})(req, res, next);
};
The actual route:
// Import the controller
const {login} = require('../controllers/auth');
// Use it in the route
router.post('/auth/login', login);

Save google authenticated user into mysql database with node.js and passport.js

I build a simple web application where the user has notes. I want the user to be able to sign in with a google account as well, but the user didn't save into the database. The local login works but the social login doesn't. Wherever I searched I only found a solution in which mongodb was used. What is the correct way with mysql?
Here is my passport.js file:
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((req, user, done) => {
conn.query("SELECT * FROM user WHERE id = ? OR facebook_id = ? OR google_id", [user.id,
user.facebook_id, user.google_id], (err, rows) => {
if (err) {
console.log(err);
return done(null, err);
}
done(null, user);
});
});
passport.use(new GoogleStrategy({
clientID: configAuth.googleAuth.clientID,
clientSecret: configAuth.googleAuth.clientSecret,
callbackURL: configAuth.googleAuth.callbackURL,
passReqToCallback: true,
profileFields: configAuth.googleAuth.profileFields
},
function (req, accessToken, refreshToken, profile, done) {
process.nextTick(function () {
conn.query("SELECT * FROM user WHERE google_id = ?", [profile.id], (err, user) => {
if (err) {
return done(err);
} else if (user) {
return done(null, user);
} else {
let newUser = {
google_id: profile.id,
google_token: accessToken,
google_email: profile.emails[0].value,
google_name: profle.name.givenName + ' ' + profile.name.familyName
};
conn.query("INSERT INTO user (google_id, google_token, google_email, google_name) VALUES (?, ?, ?, ?)",
[newUser.google_id, newUser.google_token, newUser.google_email, newUser.google_name], (err, rows) => {
if (err) {
console.log(err);
}
return done(null, newUser);
})
}
});
});
}
));
And here are the routes:
app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get('/auth/google/callback', passport.authenticate('google', {
successRedirect: '/main',
failureRedirect: '/'
}));
I can log in, I didn't receive an error message, but if I want to assign a new note to the user it doesn't add it because it doesn't save the user to the database.
I think you forget to put ? after the google_id.
Example:
google_id=?

Not a valid BCrypt hash. error is occuring

I have a problem in comparing method of bcrypt. This mthod is not able to compare password properly. Please sort out me from this problem.There is problem with comparing method its not working.I have a problem in comparing method of bcrypt. This mthod is not able to compare password properly. Please sort out me from this problem.There is problem with comparing method its not working.
app.post('/upload', (req, res) => {
// hash and save a password
const pass = bcrypt.hashSync(req.body.password);
const username = req.body.username;
console.log(bcrypt.compareSync(req.body.password, pass));
const sql = "INSERT INTO data ( password, username ) values (?,?)";
db.query(sql, [pass, username], (err, rows, fields) => {
if(!err){
res.send({
key: rows
});
}
else {
console.log(err);
}
});
})
app.post('/show', (req, res) => {
const username = req.body.username;
const password = req.body.password;
db.query("SELECT * FROM data WHERE username = ?",[username], function(err, results){
if (err) {
// console.log("error ocurred",error);
res.send({
"code":400,
"failed":"err ocurred"
})
}else{
if(results.length >0){
// console.log(bcrypt.compareSync(password, results[0].password));
if(bcrypt.compareSync(password, results[0].password)){
res.send({
"code":200,
"success":"login sucessfull"
});
}
else{
res.send({
"code":204,
"success":"Email and password does not match"
});
}
}else{
res.send({
"code":204,
"success":"Email does not exits"
});
console.log(results.length);
}
}
})
})

Not able to compare my database password and input field password

My input password and database password are same then also function is returning false. Here compare method is not working properly.I am getting false in return everytime while I am providing correct password.
app.post('/login', (req, res) => {
const username = req.body.username;
const password = req.body.password;
db.query('SELECT * FROM dataa WHERE username = ?',[username], function (error, rows, fields) {
if (error) {
// console.log("error ocurred",error);
res.send({
"code":400,
"failed":"error ocurred"
})
}else{
// console.log('The solution is: ', results);
if(rows.length >0){
console.log(bcrypt.compareSync(password, rows[0].password));
if(bcrypt.compareSync(password, rows[0].password)){
res.send({
"code":200,
"success":"login sucessfull"
});
}
else{
res.send({
"code":204,
"success":"Email and password does not match"
});
}
}
else{
res.send({
"code":204,
"success":"Email does not exits"
});
}
}
});
})
You might be having more than one username in your database which match it up with the username your are giving so it will try and match it with the first one but the password would be a different one ..

bcrypt password compare function always return false

I am using node, mysql as the server and DB and ionic on the front end. I've managed to register a user with a hash using bcrypt and attempting to authenticate the user to log them in.
When comparing the password that user enters, in bcryptJS it seems like we cannot decrypt their password. When I console.log password and the result of user lookup in my db, I am comparing the password that the user enters with the hash that's stored so i am always retuning a 400 status to the front end.
Authentication code:
app.post('/login', function(req, res) {
connection.connect(function(err) {
let email = req.body.email;
let password = req.body.password;
connection.query("SELECT * FROM sometable WHERE username = ? ", [email], function(error, results, fields) {
bcrypt.compare(req.body.password, results[0].password, function(err, result) {
console.log('>>>>>> ', password)
console.log('>>>>>> ', results[0].password)
if(result) {
return res.send();
}
else {
return res.status(400).send();
}
})
});
});
});
What's the proper way to compare the password user enters with the hash that's stored in my db?
Thanks for your help.
edit:
I've tried the below code (adding a password strings) and I'm still getting the false result... What am I missing here?
bcrypt.compare('somePassword', 'somePassword', function(err, res) {
if(res) {
console.log('true')
} else {
console.log('false')
}
});
Check to ensure you have the password before doing the comparison to know if the passwords match.
see my modification below
app.post('/login', function(req, res) {
connection.connect(function(err) {
let email = req.body.email;
let password = req.body.password;
connection.query("SELECT * FROM sometable WHERE username = ? ", [email], function(error, results, fields) {
if (results[0].password) {
bcrypt.compare(req.body.password, results[0].password, function(err, result) {
console.log('>>>>>> ', password)
console.log('>>>>>> ', results[0].password)
if(result) {
return res.send();
}
else {
return res.status(400).send();
}
})
}
});
});
});
So, as discussed in the comments of the question, the issue turned out to be the format of the column used to store the hashed password.
If you set your column to char(50) for instance, some databases will just silently remove anything beyond 50 chars, or add spaces to get to 50 chars if you have less.
This then breaks the comparison with the hashed version.
app.post('/login', function(req, res) {
connection.connect(function(err) {
let email = req.body.email;
let password = req.body.password;
connection.query("SELECT * FROM sometable WHERE username = ? ", [email], function(error, results, fields) {
if(error) throw error;
else {
if(results.length > 0) {
bcrypt.compare(req.body.password, results[0].password, function(err, result) {
if(result) {
return res.send({ message: "Login Successful" });
}
else {
return res.status(400).send({ message: "Invalid Password" });
}
});
} else {
return res.status(400).send({ message: "Invalid Email" });
}
}
});
});
});
Sorry guys! i had the some proble nut it was comming from mysql it was because i had a column callded password which was in CHAR(50) so if the hash is long than to 50 char it was truncating it, whyle hashed password are very long so i have changed the field from CHAR(50) to VARCHAR(255);
Then everything start work fine