password hashing in nodejs - javascript

I am new to StackOverflow, and to the development world. Currently learning JS and node, I am developing a personal project which will be a task management web app. I wrote the register/auth controllers for user data inserts/checks in DB (using MySQL), but ATM I am saving the password in plain text. I want to hash the password and save it in the DB, but when I go look into the table, the passed value is saved as "Object Promise", so it's not currently hashing I think. How can I correctly save the value in registration and validate it in auth? Below is the code of both auth and register controllers. Thanks.
register-controller:
var mysqlConnection = require ('../config');
const bcrypt = require ('bcrypt');
const saltRounds = 10;
module.exports.register=function(req,res){
var today = new Date();
var users={
"firstname":req.body.firstname,
"lastname" : req.body.lastname,
"email":req.body.email,
"password":bcrypt.hash(req.body.password, saltRounds),
"signup_date":today,
"last_login_date":today
}
mysqlConnection.query('SELECT count(email) as count FROM users where email = "' + req.body.email + '"', function (error, results) {
console.log(error, results[0].email);
})
mysqlConnection.query('INSERT INTO users SET ?',users, function (error, results, fields) {
console.log(error, results);
if (error) {
res.json(
error
)
}else{
console.log('User registered succesfully.');
res.redirect('/');
}
});
}
and this is auth-controller:
var mysqlConnection = require ('../config');
const bcrypt = require ('bcrypt');
module.exports.auth = function (req, res, next) {
var email = req.body.email
var password = req.body.password
console.log(email, password);
mysqlConnection.query('SELECT password FROM users where email = "' + email + '"', function (error, results) {
console.log(error, results[0]);
if (error) {
res.error = error;
}else{
if(results.length >0){
bcrypt.compare(password,results[0].password, function (err,res){
if(password === results[0].password){
console.log('User logged in succesfully.');
res.error = error;
res.user = results[0];
res.redirect('/');
}else{
res.error = error;
res.user = null;
}
}
)}
else{
res.error = error;
res.user = null;
res.redirect('/register');
}
}
next();
});
}

Related

Basic Authentication ComparePassword

I am currently working on a "Basic Authetntication" for Node JS. It should accept requests like the following:
POST http://localhost:8080/authenticate/
Authorization: Basic YWRtaW46MTIz
The AuthenticationService.js first reads the header and then passes the whole thing to the Userservice.js
AuthenticationService.js
async function basicAuth(req, res, next) {
// make authenticate path public
if (req.path === '/') {
return next();
}
if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
return res.status(401).json({ message: 'Missing Authorization Header' });
}
// verify auth credentials
const base64Credentials = req.headers.authorization.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [username, password] = credentials.split(':');
console.log("AuthenticationService "+username+" "+password);
const user = await userService.authenticate({ username, password });
if (!user) {
return res.status(401).json({ message: 'Invalid Authentication Credentials' });
}
req.user=user
res.send(user)
next();
}
module.exports = {
basicAuth
}
The user service checks if the user is found and checks if the password is valid, only then the user object is sent back to the authentication service.
UserService.js
async function authenticate({ username, password }) {
let user = await User.findOne({userID: username})
user.comparePassword(password.toString(), function(err,isMatch) {
if (err){
console.log("error")
throw err;
}
if(isMatch)
{
console.log("Password correct")
}
if(!isMatch){
console.log("Password wrong")
}});
if(user){
return user;
}
else{
return null;
}
}
module.exports = {
authenticate
}
The .comparePassword-Method is inside the Usermodel.js:
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
const User = mongoose.model("User", UserSchema);
module.exports = User;
How can I send the boolean value of isMatch in the Userservice.js outside it's scope, so I can send the userobject back to the AuthenticationService.js depending on the correct password ? How can I improve that code ?
I erase the authenticate-method in Userservice.js and just call the crud-method. After that I call the compare-method and inside the if/else-block I pass a res.send.
function basicAuth(req, res, next) {
if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
return res.status(401).json({
message: 'Missing Authorization Header'
});
}
// verify auth credentials
const base64Credentials = req.headers.authorization.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [username, password] = credentials.split(':');
console.log("AuthenticationService " + username + " " + password);
userService.findUserById(username, function(error, user) {
user.comparePassword(password.toString(), function(err, isMatch) {
if (err) {
console.log("Fehler")
throw err;
}
/*Passwort richtig*/
if (isMatch) {
res.send(user);
}
/*Passwort falsch*/
if (!isMatch) {
res.status(401).json({
message: 'Passwort und userID stimmen nicht überein.'
});
}
});
})
}

Cannot set headers after they are sent to the client Error in node.js

Cannot set headers after they are sent to the client I'm getting this error. I did some study and I think it's because of more than one callbacks but I'm unable to solve this issue. Please help me fix this issue. I'm attaching herewith my routes.js code. Any help will be highly appreciable. Thank you.
Here's my routes.js code
const {
con,g
sessionStore
} = require('./config/db');
const { route } = require('./routes/auth');
exports.new = function(req, res){
message = '';
if(req.method == "POST"){
const post = req.body;
const username= post.username;
const title= post.title;
const state= post.state;
const category= post.category;
const description= post.description;
if (!req.files)
return res.status(400).send('No files were uploaded.');
const file = req.files.uploaded_image;
var img_name=file.name;
if(file.mimetype == "image/jpeg" ||file.mimetype == "image/png"||file.mimetype == "image/gif" ){
file.mv('public/imgs/uploads/'+file.name, function(err) {
var sql = "INSERT INTO `nt_data`(`username`,`title`,`state`,`category`, `images` ,`description`) VALUES (?,?,?,?,?,?)";
var query = con.query(sql, [username, title, state, category, img_name, description], function(err) {
console.log(err)
if (!err) {
res.redirect('show/' + username);
}
else {
message = "This format is not allowed , please upload file with '.png','.gif','.jpg'";
res.render('new.ejs',{message: message});
}
});
});
}
}
else {
res.render('new');
}
};
exports.show = function(req, res){
let message = '';
var username = req.params.username;
const sql="SELECT * FROM `nt_data` WHERE `username`='"+username+"'";
con.query(sql, function(err, result){
console.log(err)
if(result.length <= 0){
message = "show not found!";
res.render('show.ejs',{data:result, message: message});
}else{
res.redirect('/places');
}
res.render('show', {data:result, message: message});
});
};
exports.places=function (req,res){
let message = '';
var username = req.params.username;
const sql="SELECT * FROM `nt_data` WHERE `username`='"+username+"'";
con.query(sql, function(err, result){
console.log(err)
if(result.length <= 0)
message = "places not found!";
res.render('places.ejs',{data:result, message: message});
});
}
In your show function you execute a database query, inside the callback you have an if else statement with a res.render and a res.redirect. So one way or the other a result is sent. So you cannot send a result when the if statement is completed.
Remove this res.render('show', {data:result, message: message});. line and you are good to go!

My API Route is not working; NodeJS

I am working on an authentication API system using NodeJS. The /Signup API endpoint is working fine, but the /authenticate is not. Everytime I call the /authenticate endpoint, I get the error message: 'Could not authenticate user' even when a valid user is provided;
Below is my code. Please tell me what I am doing wrong here
var express = require("express");
var mongoose = require("mongoose");
var User = require("../models/user");
module.exports = function (router) {
router.post('/signup', function (req,res) {
var user = new User();
user.local.username = req.body.username;
user.local.email = req.body.email;
user.local.password = req.body.password;
if (req.body.username == null || req.body.username == '' || req.body.email == null || req.body.email == '' || req.body.password == null || req.body.password == '') {
res.json({success:false, message:'Ensure username, email and password were provided'});
} else {
user.save(function (err, data) {
if (err) res.json({success:false, message:'Username or Email already exists!'});
// console.log(err.errors)
res.json({success:true, message:'New user created', data:data});
console.log(data)
});
}
})
router.post('/authenticate', function (req,res) {
User.findOne({username: req.body.username}).exec(function (err,user) {
if(err)
return res.send(err);
if (!user) {
res.json({success:false, message: 'Could not authenticate user'});
} else if(user){
var validPassword = user.comparePassword(req.body.password)
if (!validPassword) {
res.json({success:false, message: 'Could not authenticate password'});
} else{
res.json({success:true, message: 'User authenticated'});
}
}
});
});
}
EDIT
User Model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
// define the schema for our user model
var userSchema = new Schema({
local : {
username : {type:String,unique:true,required:true, lowercase:true},
email : {type:String,unique:true,required:true, lowercase:true},
password : String
},
created_at : {type:Date, default:Date.now},
updated_at : {type:Date, default:Date.now}
});
userSchema.pre('save', function(next){
var user = this;
var now = new Date();
user.updated_at = now;
if(!user.created_at){
user.created_at = now
}
bcrypt.hash(user.local.password, null, null, function (err, hash) {
if(err) return next(err)
user.local.password = hash;
next(); })
});
// checking if password is valid
userSchema.methods.comparePassword = function(password) {
return bcrypt.compareSync(password, this.local.password); };
// create the model for users and expose it to our app
module.exports = mongoose.model('User', userSchema);
just saw the bug its you have your username inside the local.
router.post('/authenticate', function (req,res) {
User.findOne({'local.username': req.body.username}).exec(function (err,user) {
if(err)
return res.send(err);
else{
}
});

Node JS MySQL Authentication

I am new to node JS. I am working on authenticating users against backend MYSQL.
Here is the code snippet of authentication
function Authenticate(username, password, fn) {
connection.connect();
var user;
connection.query('SELECT * from Users where username = ' +
connection.escape(username) + ' and password =' + connection.escape(password),
function(err, rows) {
user = rows[0].username;
});
if (!user) {
return fn(new Error('cannot find user'));
} else {
return fn(null, user);
}
connection.end();
}
This is my call back function.
app.post('/Login', function(req, res) {
Authenticate(req.body.username, req.body.password, function(err, user) {
if (user) {
req.session.regenerate(function() {
req.session.user = user;
req.session.success = 'Authenticated as ' + user;
res.redirect('Home');
});
} else {
req.session.error = 'Authentication failed, please check your username and password.';
res.redirect('Login');
}
});
})
I am getting an error, which i cannot get my head around.
TypeError: Cannot set property 'error' of undefined
at /...../.../node_modules/app.js:42:23
at Authenticate (/..../..../node_modules/app.js:82:11).
Please share your thoughts!
Takes the else out and see if any other req.session functions properly if not check if middleware is configured correctly for express validator

Matching mail and pass in mongodb node js

So, I'm new to all this and was developing a login and registration page. I can easily save the data to the database while registering through registration page, but the problem is I don't know what to do during login page. What type of statements do I have to use to match the entered email address with the email addresses of each document in the "employee" collection, and then check if the password is correctly entered.
Here is my express file main.js:
var express = require("express");
var app = express();
var connection = require("../connection");
module.exports = function(app){
app.get('/', function(req, res){
res.render("login.html");
});
app.get('/adduser', function(req, res){
res.render("login.html");
var name = req.param('name');
var email = req.param('email');
var employeeid = req.param('employeeid');
var password = req.param('password');
var position='';
var joining_date= '';
var active= 'Y';
console.log("Name: " + name + " Email: " + email + "Employee id: " +employeeid);
connection.add(name,email,employeeid,password,position,joining_date,active);
});
//CHECKING IF MAIL AND PASSWORD MATCHES
app.get('/checkuser', function(req, res){
var email = req.param('email');
var password = req.param('password');
console.log(" Email: " + email);
connection.check(email,password);
});
And this is the connection file, connection.js:
var add=function(uname,uemail,uemployeeid,upassword,uposition,ujoining_date,uactive) {
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/HippoFeedo';
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
}
else {
console.log('Connection established to', url);
// Get the documents collection
var collection = db.collection('employees');
//Create some users
var data = {name:uname,email:uemail,employeeid:uemployeeid,password:upassword,position:uposition,joining_date:ujoining_date,active:uactive };
/* var user2 = {name: 'modulus user', age: 22, roles: ['user']};
var user3 = {name: 'modulus super admin', age: 92, roles: ['super-admin', 'admin', 'moderator', 'user']};*/
// Insert some users
collection.insert(data, function (err, result) {
if (err) {
console.log(err);
} else {
console.log('Inserted %d documents into the "employees" collection. The documents inserted with "_id" are:', result.length, result);
}
db.close();
});
}
});
} //NOW CHECKING IF ENTERED EMAIL AND PASS MATCHES OR EMAIL EXISTS???
var check= function(uemail,upassword)
{
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/HippoFeedo';
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
}
else {
console.log('Connection established to', url);
var collection = db.collection('employees');
collection.findOne({uemail:uemail}, function(err,doc){ //I HAVE NO IDEA WHAT TO DO HERE??
if(err) throw err;
if(doc)
console.log("Found: "+uemail+", pass=");
else
console.log("Not found: "+uemail);
db.close();
});
}
});
}
module.exports.add=add;
module.exports.check=check;
EDITED: THE FIX FOR THE ABOVE PROBLEM IS PROVIDED BY GMANIC BELOW..
Here is the fix, you are trying to match on uemail but you saved it as email. You could even take it a step further and match on the password at the same time.
exports.check = function(uemail, upassword)
{
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/HippoFeedo';
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
}
else {
console.log('Connection established to', url);
var collection = db.collection('employees');
collection.findOne({ email: uemail, password: upassword }, function(err, doc){
if(err) throw err;
if(doc) {
console.log("Found: " + uemail + ", pass=" + upassword);
} else {
console.log("Not found: " + uemail);
}
db.close();
});
}
});
}
There are some best practices that you should add in, but to answer your question this should work.

Categories

Resources