using bcrypt for login in nodejs - html

I'm having a hard time with integrating bcrypt to try to make my login system safe.
I basically get the username, password the user inputs and try to compare it from the hashed password in my db. here's what I have.
const inputUsername = req.body.inputUsername;
const inputPassword = req.body.inputPassword;
var userLogin = "select * from login where USERNAME = ?"
ibmdb.open(ibmdbconnMaster, function(err, conn) {
if (err) return console.log(err);
conn.query(userLogin, [inputUsername], function(err, rows) {
if (err) {
console.log(err)
}
if (rows.length > 0) {
var pass = ""
for (var i = 0; i < rows.length; i++) {
pass = rows[i]['PASSWORD'];
console.log(pass)
bcrypt.compare(inputPassword, hash, function(err, result) {
if (pass == result) {
console.log("this works")
userAuth = true;
res.redirect('/index')
}
})
}
console.log("does not work")
} else {
userAuth = "false";
res.render('login.ejs')
alert('Incorrect username or password. Please try again')
}
conn.close(function() {
console.log('closed the function /login');
});
})
})
what happens right now is I get the error ReferenceError: hash is not defined
not sure how to fix this. thanks in advance

Where have you defined hash? I don't see it in your code.
Here's an example of auth routes that I've used with bcrypt/node/express:
const Users = require("../users/users-model.js");
router.post("/register", (req, res) => {
// Pull the user's credentials from the body of the request.
const user = req.body;
// Hash the user's password, and set the hashed password as the
// user's password in the request.
const hash = bcrypt.hashSync(user.password, 10);
user.password = hash;
Users.add(user)
.then((newUser) => {
const token = generateToken(newUser);
res
.status(201)
.json({ created_user: newUser, token: token, user_id: newUser.id });
})
.catch((err) => {
res.status(500).json({
message: "There was an error adding a user to the database",
err,
});
});
});
router.post("/login", (req, res) => {
const { username, password } = req.body;
Users.findBy({ username })
.first()
.then((user) => {
if (user && bcrypt.compareSync(password, user.password)) {
const token = generateToken(user);
res
.status(200)
.json({
username: user.username,
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
token: token,
user_id: user.id,
});
} else {
res.status(401).json({ message: "Invalid Credentials" });
}
})
.catch((err) => {
res.status(500).json(err);
});
});
function generateToken(user) {
const payload = {
userid: user.id,
username: user.username,
};
const options = {
expiresIn: "1h",
};
const token = jwt.sign(payload, secrets.jwtSecret, options);
return token;
}
module.exports = router;

Related

How i display username after login successful with set cookies using angular nodejs mysql

My login.component.ts file
How to set cookies in the code to display the username.
login Submit(){
console.log(this.userLogin.value)
this.service.LoginData(this.userLogin.value).subscribe((res)=>{
console.log(res)
this.userLogin.reset()
this.successmsg = res.message
this.Username = this.cookieService.set('username', this.Username)
})
}
I am trying to display the username but it only see me undefined.
api service file
LoginData(data:any):Observable<any>{
return this.http.post(`http://localhost:3000/login`,data)
}
dashboard(){
return this.http.get('http://localhost:3000/dashboard')
}
NodeJS file using MySQL database
app.post('/login', (req, res) => {
const username = req.body.username;
const password = req.body.password;
const query = `SELECT * FROM user WHERE username = '${username}' AND password = '${password}'`;
db.query(query, (error, result) => {
if (error) {
console.log('Error querying database:', error);
res.status(500).send('Error querying database');
} else if (result.length === 0) {
console.log('Invalid username or password');
res.status(401).send('Invalid username or password');
} else {
console.log('Login successful');
res.status(200).send({
message: 'Login successful',
username: username
});
}
});
res.cookie('username',`${username}`)
});

if the email is not registered in the database, then data cannot be transferred to the email, I use NodeJs, NodeMailer and MYSQL for the database

permission to ask the temperature, so I use NodeMailer to send data email, the problem is that emails that are not registered in the database can still send the data. registered"
const sendMail = async (req, res) => {
const querySearch = 'SELECT * FROM user WHERE email="' + req.body.email + '"';
const email = req.body.email;
koneksi.query(querySearch, async (err, rows, field) => {
const random = require("simple-random-number-generator");
let params = {
min: 0000,
max: 9999,
integer: true
};
const CodeRandom = random(params);
const querySql = 'UPDATE user SET ? WHERE email = ?';
koneksi.query(querySql, [{ code_verification: CodeRandom, }, req.body.email], (err, rows, field) => {
// error handling
if (err) {
return res.status(500).json({ message: 'Gagal update code!', data: { code_verification: "" } });
}
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: '***********#gmail.com',
pass: '*********'
}
});
const mailOptions = {
from: 'muthiazraihan27#gmail.com',
to: req.body.email,
subject: 'Kode Verifikasi Lupa Password',
html: '<h2>Berikut kode reset password anda:</h2><h1> ' + CodeRandom + '</h1> '
};
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
console.log(err)
res.status(500).json({ message: 'Ada kesalahan', error: err })
} else {
res.status(200).json({
success: true, data: rows[0]
})
}
})
})
})
};
in order to answer my question

Cannot set headers after they are sent to the client error when add code to redirect another page

I have login page and signup page. when a user want register account and register is successful, I want to redirect him to signin.html page. however, nothing I've tried have worked so far. I always get the error "Cannot set headers after they are sent to the client" when I add this code "res.redirect('http://localhost:3000/signin.html')". here is my code
signup.html
const form = document.getElementById('reg-form')
form.addEventListener('submit', registerUser)
async function registerUser(event){
event.preventDefault()
const username = document.getElementById('user').value
const password = document.getElementById('password').value
const password_confirmation = document.getElementById('password_confirmation').value
const phone = document.getElementById('tel').value
const result = await fetch('/register',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password,
password_confirmation,
phone
})
}).then((res) => res.json())
if (result.status === 'ok') {
alert('success')
}else {
alert (result.error)
}
}
and here is server.js
const express = require('express')
const path = require ('path')
const mongoose = require ('mongoose')
const User = require ('./model/user')
const bodyParser = require('body-parser')
const bcrypt = require ('bcryptjs')
const jwt = require ('jsonwebtoken')
const JWT_SECRET = 'lkjlfg%nlnkllkj#R%##%#&bgkj3nskk2cnklvdfsflkjlkjf98748'
const port =3000
mongoose.connect('mongodb://localhost:27017/login-app-db', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
const app = express()
app.use('/', express.static(path.join(__dirname, '../code FE/')))
app.use(bodyParser.json())
// app.post('/api/change-password', (req, res) => {
// const { token } = req.body
// const user = jwt.verify(token, JWT_SECRET)
// console.log()
// })
app.post('/signin', async (req, res) => {
const { username, password } = req.body
const user = await User.findOne({ username }).lean()
console.log(password)
if (!user) {
return res.json({status: 'error', error: 'Invalid username/password'})
}
if (await bcrypt.compare('password', user.password)) {
// the username, password combination is successfully
const token = jwt.sign({
id: user._id,
username: user.username
},
JWT_SECRET
)
return res.json({status: 'ok', data: token})
}
return res.json({status: 'error', error: 'Invalid username/password'})
})
app.post('/register', async (req, res) => {
console.log(req.body)
const { username, password: plainTextPassword, password_confirmation: someOtherPlaintextPassword, phone} = req.body
if (!username || typeof username !== 'string') {
return res.json({ status: 'error', error: 'Invalid username'})
}
if (!plainTextPassword || typeof plainTextPassword !== 'string') {
return res.json({ status: 'error', error: 'Invalid password'})
}
const password = await bcrypt.hash('password', 10)
const password_confirmation = await bcrypt.hash('password_confirmation', 10)
try {
const response = await User.create({
username,
password,
password_confirmation,
phone
})
console.log('user created successfully: ', response)
res.redirect('http://localhost:3000/signin.html')
}catch(error){
if (error.code === 11000) {
return res.json({ status: 'error', error: 'username already in use'})
}
throw error
}
res.json({status: 'ok'})
})
app.listen(port, () => {
console.log(`Example app listening on port http://localhost:${port}`)
})

Strange nodejs behaviour when logging in a user

The problem is that it shows that it is successfully logged in (201) without the redirect code, but with it, it shows a 302 error and the email_address is undefined.
What could be the problem here? I still can't come to a conclusion.
The problem may be in the order of the code I guess?
const login = async (req, res, next) => {
const { email_address, password, user_email, user_password}: { email_address: string, password: string, user_email: string, user_password: string } = req.body;
try {
const userWithDetails = 'SELECT * FROM users WHERE email_address = user_email AND password = user_password'; //w form info
if (userWithDetails) {
req.session.loggedin = true; //true
req.session.email_address = email_address; //undefined
console.log(req.session.email_address)
// return res.redirect('./index.html')
}
res.status(201).send('Succesfully signed in');
// res.status(403).send('Password is not correct');
} catch(error) {
res.status(404).send(`User with email ${email_address} not found!`);
}
await next;
};
NEW CODE ***
const login = async (req, res, next) => {
const { email_address, password}: { email_address: string, password: string} = req.body;
const userWithDetails = 'SELECT * FROM users WHERE email_address = ?';
return con.query(userWithDetails, email_address, (err, results) => {
if (err) {
console.error(err);
}
const user = results.find(emailObj => emailObj.email_address === email_address);
if (results && results.length && user.email_address) {
req.session.loggedin = true;
req.session.email_address = email_address;
const matchPassword: boolean = bcrypt.compareSync(password, user.password);
if (matchPassword) {
const token = jwt.sign({ user }, 'aaaa', { expiresIn: '1h'});
res.status(200).send({message: 'Logged in', token: token});
} else {
res.status(403).send('Password is not correct');
}
} else {
res.status(404).send(`User with email ${email_address} not found!`);
}
});
await next;
}
You don't execute your sql query at any point.
You just say :
query = 'select blabla'
if(query){...}
Of course this will always be true. You want to run the query on your database.
Also in your query you don't properly use the variables, see string formatting :
let my_var = `SELECT xxx from xxx where username = '${username}'`
Also please sanitize the parameters to prevent SQL Injection...

passport authentication callback not calling passport middleware

I am trying to test if a GET request to a specific route is protected by using JSON Web Tokens with passport JwtStrategy; however, it seems like the passport.use middleware function I have in my server.js file is not executing. The console.log I have in there never shows up in my shell/terminal. My login route works, but not the profile route. I am using postman and I entered http://localhost:3000/profile for the GET method and in the Headers tab I chose Authorization for Key and for the Value I copied and pasted the long JSON web token string, but it keeps saying unauthorized. That is because my passport.use function is never getting executed.
//Server.js file
var JwtStrategy = require("passport-jwt").Strategy;
var ExtractJwt = require("passport-jwt").ExtractJwt;
var User = require("../models/user");
var config = require('./secret');
app.use(passport.initialize());
app.use(passport.session());
let options = {};
//pass token back and forth
options.jwtFromRequest = ExtractJwt.fromAuthHeader();
options.secretOrKey = config;
passport.use(new JwtStrategy(options, (jwt_payload, done) => {
*******************************************
//this console log doesn't show up in shell which makes be believe its never getting here
*******************************************
console.log("JWT PAYLOAD", jwt_payload)
User.getUserById(jwt_payload._id, (err, user) => {
if(err){
return done(err, false);
}
if(user){ //null for error
return done(null, user);
}else{
return done(null, false);
}
});
}));
//Routes file where the passport.authenticate callback is called
var passport = require('passport');
var jwt = require('jsonwebtoken');
var secret = require('../config/secret')
var User = require('../models/user');
router.post('/login', (req, res) => {
var username = req.body.username;
var password = req.body.password;
console.log("SECRET2", secret);
console.log("SECRET", secret.secret);
User.getUserByUsername(username, (err, user) => {
if(err){
throw err;
}
if(!user){
return res.json({ success: false, msg: "User not found"});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if(err){
throw err;
}
if(isMatch){
var token = jwt.sign(user, secret.secret, {
expiresIn: 604800 //1 week in seconds, token expires and requires to log back in
});
console.log('TOKEN IN LOGIN ROUTE', token)
res.json({
//tokens are then stored in local storage or cookie
success: true,
token: 'JWT ' + token,
user: {
id: user._id,
name: user.name,
username: user.username,
email: user.email
}
});
}else{
return res.json({ success: false, msg: "Incorrect password"});
}
});
});
});
router.get('/profile', passport.authenticate('jwt', {session:false}), (req, res) => {
res.json({user: req.user});
});
//User model
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name: {
type: String,
trim: true,
required: "First Name is Required"
},
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
var User = mongoose.model("User", UserSchema);
module.exports = User;
//Alternate syntax for exporting Schema
// var User = module.exports = mongoose.model("User", UserSchema);
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback){
var query = { username: username }
User.findOne(query, callback);
}
//Custom User model function that will take in the newUser object and hash the password.
module.exports.addUser = function(newUser, callback){
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err){
throw err
}
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.comparePassword = function(password, hash, callback){
bcrypt.compare(password, hash, (err, isMatch) => {
if(err){
throw err
}
callback(null, isMatch);
});
}
Update:
I tried putting a space after 'JWT' in for the value for Authorization in the postman, but it still does not work and the console log is not showing. Is it because I am somehow not exporting or linking the passport.use I have defined in my server.js to my GET '/profile' route in my routes file?
Update 2: Added model and Login route
Maybe it is necessary to include more code to see your issue, but it seems like the strategy is not being exported correctly. When you create a new strategy, you can include an 'alias' to use it in the entry point:
passport.use('local-login', new JwtStrategy(options, (jwt_payload, done) => {
....
}
router.get('/profile', passport.authenticate('local-login', {session:false}), (req, res) => {
res.json({user: req.user});
});