Node.js Synchronous call on passport local signup - javascript

I've been trying to get along with Node.js and I'm struggling to learn a few core things. My problem is in passport I dont know how to make a synchronous call. What I want is: If there is a user with the signup email already, I dont want to create it, ill throw a flash message, otherwise i'll create the user. I'm not sure how to only create the user after the check up for the email uniqueness. I tried it with return true/false in a if statement but it just doesn't seem right.
I adapted my code from scotch.io's passport tutorial.
// passport.js
// load all the things we need
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var User = require('../app/models/user');
// expose this function to our app using module.exports
module.exports = function(passport) {
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
if(!User.isEmailInUse(req)){
var newUser = {};
//create the user
User.createUser(req, newUser),
function (){
console.log('function ception ' + newUser)
if(newUser){
return done(null, newUser, req.flash('signupMessage', 'Great success!'));
}else{
return done(null, false, req.flash('signupMessage', 'An error has occurred.'));
}
};
console.log('what now?');
}else{
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}
}));
};
// user.js
var mysql = require('../../config/database.js').mysql;
var bcrypt = require('bcrypt-nodejs');
// Create user.
module.exports.createUser = function(req, res){
var input = JSON.parse(JSON.stringify(req.body));
var salt = bcrypt.genSaltSync(10);
var currentdate = new Date();
var datetime = currentdate.getFullYear() + "/"
+ (currentdate.getMonth()+1) + "/"
+ currentdate.getDate() + " "
+ currentdate.getHours() + ":"
+ currentdate.getMinutes() + ":"
+ currentdate.getSeconds();
// create the user
var newUserMysql = {
email: input.email,
password: bcrypt.hashSync(input.password, salt, null), // use the generateHash function in our user model
isActive: 1,
createdAt: datetime
};
var insertQuery = "INSERT INTO tUsers ( usrEmail, usrPassword, usrIsActive, usrCreatedAt ) values (?,?, ?, ?)";
console.log('about to run insert into');
mysql.query(insertQuery,[newUserMysql.email, newUserMysql.password, newUserMysql.isActive, newUserMysql.createdAt],function(err, rows) {
if(!err){
newUserMysql.id = rows.insertId;
console.log('returning user');
res = newUserMysql;
}else{
console.log(err);
res = null;
}
});
};
module.exports.isEmailInUse = function(req){
var input = JSON.parse(JSON.stringify(req.body));
var selectQuery = "SELECT * FROM tUsers WHERE usrEmail = ?";
var query = mysql.query(selectQuery, [input.email], function(err, rows, fields) {
console.log(query.sql);
if (!err){
if(rows > 0){
return true;
}
console.log('The solution is: ', rows);
return false;
}
else
{
console.log('Error while performing Query -> ' + err);
return false;
}
});
};

You need to return a callback in the function isEmailInUse.
Inside this function you are calling the mysql.query that is runing an asyn call to the database.
change the function isEmailInUser to:
module.exports.isEmailInUse = function(req, callback){
var input = JSON.parse(JSON.stringify(req.body));
var selectQuery = "SELECT * FROM tUsers WHERE usrEmail = ?";
var query = mysql.query(selectQuery, [input.email], function(err, rows, fields) {
console.log(query.sql);
if (!err){
if(rows > 0){
return callback(null, true);
}
console.log('The solution is: ', rows);
return callback(null, false);
}
else {
console.log('Error while performing Query -> ' + err);
return callback(err, false);
}
});
};
And to use it:
IsEmailInUser(req, function(err, inUse){
if(isUse){
//create code
}
else {
//send error to user
}
});

Related

Post route returning nothing

I've been following a guide on implementing a password reset in Node. I'm working on the password reset post route below and when I post nothing seems to happen, it justs reloads the reset page. ive added some console.log() in various places on the code but they dont get executed. Hope someone can assist. ive deleted the other routes to make the code shorter
var express = require('express');
var router = express.Router({ mergeParams: true });
var Kids = require('../models/kid');
var User = require('../models/user');
var async = require('async');
var nodemailer = require('nodemailer');
var crypto = require('crypto');
var middleware = require('../middleware');
//password reset
router.get('/password_reset', function (req, res) {
res.render('password_reset');
});
//posting the account email reset
router.post('/password_reset', function (req, res, next) {
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ email: req.body.email }, function(err, user) {
if (!user) {
req.flash('error', 'No account with that email address exists.');
return res.redirect('/forgot');
}
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'SendGrid',
auth: {
user: 'Hidden',
pass: 'Hidden'
}
});
var mailOptions = {
to: user.email,
from: 'passwordreset#demo.com',
subject: 'Node.js Password Reset',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/reset/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
req.flash('info', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
done(err, 'done');
});
}
], function(err) {
if (err) return next(err);
res.redirect('/forgot_reset');
});
});
module.exports = router;
i figured out the issue, it was to do with my form. I had forgotten to add:
<form method="post" action="/password_reset">
so the form was not sending anything.

The right way to connect to query database mongodb multiples times

im building a website in my free time using nodejs/Handlebars.js/mongodb(mongoose),
i didnt study any web developement lessons, and i dont know the right way to do things efficiently and securely.
so in this project, i stumbled upon a problem where i had to query in the database if email already exists or no if it does, it queries again if the username already exists or not, if it does exists the user can be registred to the databse. yes it gets the job done but im not satisfyied with this approach, it seems to be unprofessional and not secure.
so can you please tell me the right way to do it ?
this is the part where i think i ve done it the wrong way
//check for errors in Req.validation and push them to errors Array
if(valErrors){
for (var i = 0; i < valErrors.length; i++) {
errors.push(valErrors[i])
}
}
//check if the username submitted exists in the database
User.findOne({'username':username}, function (err, user) {
if(user)
{
errors.push({msg:"username is already in use!"})
res.render('user/register',{
errors:errors
});
}
//if the username is not in use already check if the email is in
//use
else {
User.findOne({'email':email}, function (err, user) {
if(user){
errors.push({msg:'email is already in use !'})
res.render('user/register',{
errors:errors
});
} //if the email doesnt exists too then register this //user
else{
var coins = new Coins()
var newUser = new User({
name: name,
email:email,
username: username,
password: password,
coins:coins.encryptcoins('0'),
joindate:getDate()
});
User.createUser(newUser, function(err, user){
if(err) throw err;
});
req.flash('success_msg', 'You are registered and can now login');
res.redirect('/user/login');
}
});
}
});
})
EDIT:
user Schema
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
// User Schema
var UserSchema = mongoose.Schema({
username: {
type: String,
index:true,
required:true
},
password: {
type: String,
required:true
},
email: {
type: String,
required:true
},
name: {
type: String,
required:true
},
coins: {
type:String,
required:true
},
joindate: {
type:String,
required:true
},
orders: {
type:Array,
required:false
}
},{collection:'Users'});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.createUser = function(newUser, callback){
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
callback(null, isMatch);
});
}
this is the whole code
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/users');
const ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn();
const ensureLoggedOut = require('connect-ensure-login').ensureLoggedOut();
var Coins = require('../models/coins');
// Register
router.get('/register',ensureLoggedOut, function(req, res){
res.render('user/register');
});
// Login
router.get('/login',ensureLoggedOut, function(req, res){
res.render('user/login');
});
// Register User
router.post('/register', function(req, res){
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
console.log(email)
console.log(username)
// Validation
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('username', 'Username is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
//Error handling
var errors = [];
var valErrors = req.validationErrors()
//check for errors in Req.validation and push them to errors Array
if(valErrors){
for (var i = 0; i < valErrors.length; i++) {
errors.push(valErrors[i])
}
}
//check if the username submitted exists in the database
User.findOne({'username':username}, function (err, user) {
if(user)
{
errors.push({msg:"username is already in use!"})
res.render('user/register',{
errors:errors
});
}
//if the username is not in use already check if the email is in
//use
else {
User.findOne({'email':email}, function (err, user) {
if(user){
errors.push({msg:'email is already in use !'})
res.render('user/register',{
errors:errors
});
} //if the email doesnt exists too then register this //user
else{
var coins = new Coins()
var newUser = new User({
name: name,
email:email,
username: username,
password: password,
coins:coins.encryptcoins('0'),
joindate:getDate()
});
User.createUser(newUser, function(err, user){
if(err) throw err;
});
req.flash('success_msg', 'You are registered and can now login');
res.redirect('/user/login');
}
});
}
});
})
passport.use(new LocalStrategy(
function(username, password, done) {
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
return done(null, false, {message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
router.post('/login',
passport.authenticate('local', {successReturnToOrRedirect: '/', failureRedirect:'/user/login',failureFlash: true}),
function(req, res) {
res.redirect('/');
});
router.get('/logout',ensureLoggedIn, function(req, res){
req.logout();
req.session.destroy();
res.redirect('/');
});
module.exports = router;
function getDate(){
var d = new Date()
return ("date: "+d.getDate()+"/"+(d.getMonth()+1)+"/" +d.getFullYear() + " time GMT+1: "+(d.getHours()+1)+":"+(d.getMinutes())).toString()
}
// replaced with Ensure loging in library !
// function ensureLoggedIn(req, res, next) {
// if(req.user){
// return next()
// }else{
// res.redirect('/user/login');
// }
// }
// function ensureLoggedOut(req, res, next) {
// if(!req.user){
// return next()
// }else{
// res.redirect('/');
// }
// }
In general, for a logical unit of work send to a Database Management System (DBMS) (i.e., MongoDB server), it is imperative to group the individual operations in a single transaction. This way, you can avoid inconsistencies that might result from concurrent user creation in your database.
To be more precise, in your project the registration process checks for the following:
Check if email exists
Check if username exists
If queries 1 and 2 returned an empty result set, register a new user
In essence, those 3 steps need to take place in an atomic fashion, which means that they occur as a single logical unit (Transaction). If not, in the extreme case that 2 concurrent clients try to register users with the same usernames, then your database will result with two users with the same username.
Therefore, you should update your code to do the following:
Initiate a transaction
Check for users with the given email (user_email) and or usernamae (user_name)
If the query of step 2 returned a user, then rollback the transaction; Otherwise, insert a new user with user_email and user_name.
Commit Transaction
I am not sure whether MongoDB supports Transactional Consistency, and this is one of the reasons that I suggested using an RDBMS. Also, if it doesn't, I am sure that you can figure out a schema that identifies a single user based on email/username and try to perform the registration as a transaction.
Finally, it is considered good practice to have most of the processing take place in the DBMS side with the use of Stored Procedures.
I hope this helps.

Node.js sql injection parse error

I almost finished my register but I found some vulnerability.
Whenever I add: ?Smith into my register form, I receive the error:
Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '??Smith' at line 1
Vulnerable line (line 86):
connection.query('SELECT * FROM penguins WHERE username = ?' + username, function(err, rows) { + connection.escape(email); + connection.escape(username); + connection.escape(req.body.email); + connection.escape(req.body.nickname);
I tried to escape it with connection.escape(); but it didn't work. Email, username and password are all vulnerable inputs.
My passport strategy:
const dateTime = new Date().getTime();
const timestamp = Math.floor(dateTime / 1000);
var mysql = require('mysql');
var LocalStrategy = require('passport-local').Strategy;
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root'
});
connection.config.queryFormat = function (query, values) {
if (!values) return query;
return query.replace(/\:%'"=-?(\w+)/g, function (txt, key) {
if (values.hasOwnProperty(key)) {
return this.escape(values[key]);
}
return txt;
}.bind(this));
};
connection.query('USE kitsune');
// expose this function to our app using module.exports
module.exports = function(passport) {
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
connection.query('SELECT * FROM penguins WHERE id = ?' + id, function(err, rows) { + connection.escape(id);
connection.escape(id);
id.toString();
done(err, rows[0]);
});
});
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'username',
passwordField: 'password',
gameusernameField: 'username',
nicknameField: 'nickname',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
// here you read from req
const email = req.body.email
const nickname = req.body.nickname
const inventory = '%1'; // This is what the user gets on register. You can set this to anything that you want like: %1%2%3%4%5%6%7%8%9%10%11%12%13%14%15%16
const moderator = '0';
//const registrationdate = timestamp
const igloo = '1';
const igloos = '1';
console.log("Inventory is set to: " + inventory);
console.log("Moderator is set to: " + moderator);
console.log("Igloo is set to: " + igloo);
console.log("Igloos is set to: " + igloos);
passport.serializeUser(function(username, done) {
done(null, username);
});
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
connection.query('SELECT * FROM penguins WHERE username = ?' + username, function(err, rows) { + connection.escape(email); + connection.escape(username); + connection.escape(req.body.email); + connection.escape(req.body.nickname);
username.toString();
password.toString();
email.toString();
console.log(rows);
console.log("above row object");
if (err) return done(err);
if (rows.length) {
return done(null, false, req.flash('signupMessage', 'That username is already taken.'));
} else {
// if there is no user with that email
// create the user
var newUserMysql = new Object();
newUserMysql.igloos = igloos;
newUserMysql.igloo = igloo;
//newUserMysql.registrationdate = registrationdate;
newUserMysql.moderator = moderator;
newUserMysql.inventory = inventory;
newUserMysql.email = email;
newUserMysql.password = password; // use the generateHash function in our user model
newUserMysql.username = username;
newUserMysql.nickname = nickname;
var insertQuery = "INSERT INTO penguins (igloos, igloo, moderator, inventory, email, password, username, nickname ) VALUES ('1','1','" + moderator + "','" + inventory + "','" + email + "', + UPPER(MD5('" + password + "')), '" + username + "', '" + username + "')"; + connection.escape(username); + connection.escape(password); + connection.escape(nickname); + connection.escape(email);
connection.escape(nickname);
connection.escape(inventory);
connection.escape(igloo);
connection.escape(igloos);
connection.escape(moderator);
connection.escape(id);
connection.escape(username);
connection.escape(email);
connection.escape(nickname);
connection.escape(password);
username.toString();
password.toString();
igloos.toString();
igloo.toString();
moderator.toString();
inventory.toString();
email.toString();
nickname.toString();
id.toString();
console.log(insertQuery);
connection.query(insertQuery, function(err, rows) {
newUserMysql.id = rows.insertId;
return done(null, newUserMysql);
});
}
});
}));
// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, username, nickname, done) { // callback with email and password from our form
connection.query('SELECT * FROM penguins WHERE username = ?' + username, function(err, rows) {
username.toString();
connection.escape(username);
if (err) return done(err);
if (!rows.length) {
return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash
}
// if the user is found but the password is wrong
if (!(rows[0].password == password)) return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata
// all is well, return successful user
return done(null, rows[0]);
});
}));
}
You're mixing string concatenation with placeholders. In short:
Never use something like this but it's technically valid even though it's vulnerable:
connection.query('SELECT * FROM penguins WHERE username = ' + username, ...
Always use something like this which is valid and not vulnerable:
connection.query('SELECT * FROM penguins WHERE username = ?', username, ...
Mixing both like this will create a syntax error:
connection.query('SELECT * FROM penguins WHERE username = ?' + username, ...
because the 'SELECT * FROM penguins WHERE username = ?' string will get concatenated with the value of username and will likely produce something like:
'SELECT * FROM penguins WHERE username = ?johndoe'
which is not valid SQL. Escaping the string will not help here.
See this answer for more details about character escaping and placeholders:
How to escape mysql special characters with sockets.io/node.js/javascript
I found the issue.
Vulnerable line: connection.query('SELECT * FROM penguins WHERE username = ?', username, ...
The last part: username = ?
If someone registers with ? in it, it CREATES the SQL error.
A simple fix: connection.query("select * from penguins where id = "+id,function(err,rows){
Another fix: connection.query("select * from penguins where username = '"+username+"'",function(err,rows){
Cheers!

Node with Passport: Compare Password throws error undefined is not a function, when it returns return done(null, user);

I have read all the related questions and responses and still can't fix this issue. Please see the code below and help me understand why terminal is throwing 'undefined is not a function'.
For a rundown of the functions:
The query section looks up SQL gets the users PW from DB. Parse results gets just the pw and eliminates the 'key' from the key value pair. Move pw function is there just as a buffer so that compare PW will not execute until we have retrieved the pw to compare with.
I have been stuck on this for a while, any help is much appreciated. To see the running app, go here...a working un/pw combo are user5 1234, but bc of the error it will look up username, password, verify that its a match (the compare pw and the look up pw functions actually do work and tell you if its a existing pw and un combo, but when i try and return done(user, null) to the passport login route, it crashes...
https://[redacted].com/
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var db = require('../database');
var returnedPw;
var flash = require('connect-flash');
var session = require('express-session');
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 's',
user : 'n',
password : '',
database : 's'
});
//stripped credentioals
// Include User Model
var User = require('../models/user');
// Include Student Model
var Client = require('../models/client');
// Include Instructor Model
var Company = require('../models/company');
router.get('/signup', function(req, res, next) {
res.render('users/signup');
});
router.post('/signup', function(req, res, next){
// Get Form Values
console.log('starting post and making new user');
var first_name = req.body.first_name;
var last_name = req.body.last_name;
var street_address = req.body.street_address;
var city = req.body.city;
var state = req.body.state;
var zip = req.body.zip;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
var type = req.body.type;
// Form Field Validation
req.checkBody('first_name', 'First name field is required').notEmpty();
req.checkBody('last_name', 'Last name field is required').notEmpty();
req.checkBody('email', 'Email field is required').notEmpty();
req.checkBody('email', 'Email must be a valid email address').isEmail();
req.checkBody('username', 'Username field is required').notEmpty();
req.checkBody('password', 'Password field is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if(errors){
res.render('users/signup', {
errors: errors,
first_name: first_name,
last_name: last_name,
street_address: street_address,
city: city,
state: state,
zip: zip,
email: email,
username: username,
password: password,
password2: password2
});
} else {
var newUser = new User({
email: email,
username:username,
password: password,
type: type
});
console.log('calling post to database file to receive new user:' + newUser)
// THIS IS WHERE WE ARE POSTING THE NEW USER TO THE DATABASE!!!
db.postUsers(newUser);
var newClient = new Client({
first_name: first_name,
last_name: last_name,
address: [{
street_address: street_address,
city: city,
state: state,
zip: zip
}],
email: email,
username:username
});
if(type == 'client'){
//User.saveClient(newUser, newClient, function(err, user){
// console.log('Client created');
///}); works but replacing w sql
} else {
var newCompany = new Company({
first_name: first_name,
last_name: last_name,
address: [{
street_address: street_address,
city: city,
state: state,
zip: zip
}],
email: email,
username:username
});
//works but replacing w sql
//User.saveCompany(newUser, newCompany, function(err, user){
// console.log('Company created');
//});
//sql save function
console.log('calling sql save..');
//db.postUsers(newUser, newClient);
}
req.flash('success','User added');
res.redirect('/');
}
});
<!--//// -USER AUTH SECTION- \\\\--!><!--//// -USER AUTH SECTION- \\\\--!><!--//// -USER AUTH SECTION- \\\\--!>
/*
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function (err, user) {
done(err, user);
});
}); */
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
router.post('/login',passport.authenticate('local',{failureRedirect:'/', failureFlash:'Wrong Username or Password'}), function(req, res){
req.flash('success','You are now logged in');
var usertype = req.user.type;
res.redirect('/'/*+usertype+'s/classes' */);
});
passport.use(new LocalStrategy(
function(username, password, done ) {
console.log('in users the username is ' + username)
connection.query('SELECT password FROM t_user WHERE username = ?', username, function(err, user) {
parseResults(user, done);
});// end query
function parseResults(user, done) {
Object.keys(user)[0];
var key = Object.keys(user)[0];
user[key];
var storedPw = user[key];
for(var i in storedPw){
returnedPw = storedPw[i];
}
console.log('returnedPw is defined here ' +returnedPw);
movePw(returnedPw, done);
}// end function
var candidatePassword = password;
function movePw (returnedPw, done) {
if (returnedPw ) {
User.comparePassword(candidatePassword, returnedPw, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
//return done(null, user);
// req.flash('success','User Access Granted');
//console.log('go head')
user = username;
return done(null, user);
//done(null, user);
//notifyOuterScope();
//return true;
} else {
console.log('Invalid Password');
// Success Message
req.flash('failureFlash','User Access Denied. False Password');
return done(null, false, { message: 'Invalid password' });
}
});
}
else {console.log('return PW not defined')}
}
}// end outer function ?
));//end passport
// Log User Out
router.get('/logout', function(req, res){
req.logout();
// Success Message
req.flash('success', "You have logged out");
res.redirect('/');
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/')
}
/* COMPARING PASSWORDS */
/* where are we returning the password from the user db profile?
bcrypt.hash('mypassword', 10, function(err, hash) {
if (err) { throw (err); }
bcrypt.compare('mypassword', hash, function(err, result) {
if (err) { throw (err); }
console.log(result);
});
});
*/
module.exports = router;
The code is a working example of using SQL and passport.js with node. I was having difficulty using the Local Strategy required for passport (using sql commands instead of mongodb commands that you see in most passport documentation), and it turns out the reason is because I wasn't passing the correct variables/ was also passing in unnecessary variables.
I corrected it above. Instead of using the User.FindOne Mongo db query in local strategy, this is an example of how to do the same username/ password querys using SQL, within passport local strategy. There isn't much documentation on using SQL and passport / node.

why is mysql query "select count(*) from table" returning "[object Object]" as the result?

I have a node js/express.js server and I am attempting to create a login function for my website using passport.js. I am NOT using MongoDB to store user info. Instead, I want to use my own AmazonAWS RDS MySQL instance as my database. This means I cannot use Mongoose.
As a result, I need to query for users without Mongoose to verify their credentials in Passport.js. My RDS instance has a table called Users that contains users with just the userName and password. Each record (user) in the table is also assigned its own unique usersObjectID number. I am attempting to query the users based on the user-name that the end-user will input into the login form and matching that user-name with a record in the table.
This is my server-side code:
var connection = mysql.createConnection(
{
//database connection info
}
connection.connect(function(error)
{
if(error)
{
console.log('MySQL error: '+error);
}
else
{
console.log('Successfully connected to MySQL database');
}
});
passport.use(new LocalStrat({
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done) {
//query user from DB
var usersObjectID = -1;
var tableLength = connection.query("select count(*) from Users");
console.log("this is the length of the table: "+tableLength);
for(var i = 0; i < tableLength; i++)
{
if(connection.query("select userName from Users where Users.usersObjectID = '"+i+"'") == username)
{
console.log(connection.query("select userName from Users where Users.usersObjectID = '"+i+"'"));
usersObjectID = i;
}
}
if(usersObjectID == -1)
{
//user not found
return done(null, false, {message: "The user is not exist"});
console.log("user does not exist");
}
else if(usersObjectID != -1 && connection.query("select userName from Users where Users.usersObjectID = '"+usersObjectID+"'") != connection.query("select password from Users where Users.usersObjectID = '"+usersObjectID+"'"))
{
// if password does not match
return done(null, false, {message: "Wrong password"});
console.log("password incorrect");
}
else
{
// if everything is OK, return null as the error
// and the authenticated user
return done(null, user);
console.log("successfully logged in");
}
}
));
This is my post method:
app.post('/login', function (req, res, next) {
var uname = req.body.username;
var pass = req.body.password;
var rem = req.body.remember_me;
console.log(uname+", "+pass+", "+rem);
// ask passport to authenticate
passport.authenticate('local', function(err, user, info) {
if (err) {
// if error happens
return next(err);
console.log("err");
}
if (!user) {
return res.redirect('/login');
console.log("!user");
}
// if everything's OK
req.logIn(user, function(err) {
if (err) {
return next(err);
}
console.log("ok");
return res.redirect('/');
});
})(req, res, next);
});
Here are my questions:
When I query
var tableLength = connection.query("select count(*) from QCBIMS.Users");
console.log("this is the length of the table: "+tableLength);
I get this result:
this is the length of the table: [object Object]
Why?
Would this be a good way to go about using an RDS instance for my user info and login function?
Encountered the same problem and solved it using the FF steps:
Use alias in the SELECT STATEMENT, like: "SELECT COUNT(*) AS total from QCBIMS.Users" Note: Using alias will make it easier to find it later
Select the first [key:value] pair from list & stringify as JSON: let resultStr=JSON.stringify(tableLength[0]) Note: I Used 'tableLength' from the query above. After stringify, result can be like
this: [{"total":"1541"}]
parse result as JSON: let itemPair = JSON.parse(resultStr)
get value using the 'alias' from SQL query: let value = itemPair[0].total
IF YOU WANNA SEE THE CONTENT OF THE [object Object], you can do this:
Object.keys(queryResult).forEach(function (key) {
console.log(JSON.stringify(queryResult[key]));
});
Why not use the query following way
connection.query('select count(*) as total from Users',function(err,rows){
var tableLength = rows[0];
// do the other stuff here
});
try
const count = rows.item(0)["count(*)"];

Categories