Why the hash value is undefined? - node.js

Value of salt is logged correctly but hash is giving undefined.
I am unable to figure out what is incorrect here.
users.js is a model and the other code is a controller.
users.js
UserSchema.statics.updateOTPOnDatabase = function(mobile,otp){
bcrypt.genSalt(10, function(err, salt){
console.log(salt); //this works fine
bcrypt.hash(otp, salt, function(err, hash){
console.log(hash); //giving undefined
});
})
}
login.js
exports.login = (req, res) => {
const mobile = _.pick(req.body, ['mobile_number']);
User.findByMobile(mobile).then((user) => {
const otp = Math.round(Math.random()*9000 + 1000);
User.updateOTPOnDatabase(user.mobile_number, otp).then(res => {
console.log(res);
}).catch(err => {
var response = {
status: 'failure',
message: err.message
};
res.send(response);
});
}).catch(err => {
var response = {
status: 'failure',
message: err.message
}
res.send(response);
});
};

The only issue I can see is with your updateOTPOnDatabase function, as in this function you are accepting 1 parameter otp but when you call this function you are passing 2 parameters user.mobile_number,otp
This is your definition
UserSchema.statics.updateOTPOnDatabase = function(otp){ }
This is how you are invoking it
User.updateOTPOnDatabase(user.mobile_number, otp) { }
So you might need to fix 1 or the other and also check if user.mobile_number is not returning undefined or null
Edit 2
As per the comment and per Github code, a string is expected so you can convert otp to string by using .toString() method
UserSchema.statics.updateOTPOnDatabase = function(mobile,otp){
bcrypt.genSalt(10, function(err, salt){
console.log(salt);
bcrypt.hash(otp.toString(), salt, function(err, hash){
console.log(hash);
});
})
}

Related

Login Authentification: No response from Rest API after Post Request

I recently switched from php development to Javascript (I'm really amazed by the performance and possibilities).
Currently I try to create a simple authentification function (Username,hashed Password checked to mariadb Database)
After following some tutorials I managed to create the following structure:
But when I try to test the API via Postman and Insomnia I just get no response. Not even an Error Code. Just going on forever, just like an infinite Loop?
I'm thankful for any tip as I'm new to this. Thanks in advance.
My Stack: React, Nodejs, Mariadb, Express & Jwt / bcryptjs
My Express Router router.js:
router.post('/login', (req, res, next) => {
pool.query(
`SELECT * FROM TABLE WHERE username = ${pool.escape(req.body.username)};`,
(err, result) => {
// user does not exists
if (err) {
throw err;
return res.status(400).send({
msg: err
});
}
if (!result.length) {
return res.status(401).send({
msg: 'Username or password is incorrect!'
});
}
// check password
bcrypt.compare(
req.body.password,
result[0]['password'],
(bErr, bResult) => {
// wrong password
if (bErr) {
throw bErr;
}
if (bResult) {
const token = jwt.sign({
username: result[0].username,
userId: result[0].id
},
process.env.API_SecretKey, {
expiresIn: '2h'
}
);
return res.status(200).send({
msg: 'Logged in!',
token,
user: result[0]
});
}
return res.status(401).send({
msg: 'Username or password is incorrect!'
});
}
);
}
);
});
router.post('/sign-up', userMiddleware.validateRegister, (req, res, next) => {
pool.query(
`SELECT * FROM TABLE WHERE LOWER(username) = LOWER(${pool.escape(
req.body.username
)});`,
(err, result) => {
if (result.length) {
return res.status(409).send({
msg: 'This username is already in use!'
});
} else {
// username is available
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).send({
msg: err
});
} else {
// has hashed pw => add to database
pool.query(
`INSERT INTO TABLE (SecurityID, userPassword, username, userOTP) VALUES ('${pool.escape}', ${pool.escape(
req.body.SecurityID,
req.body.username,
req.body.password,
req.body.userOTP
)}, ${pool.escape(hash)}, now())`,
(err, result) => {
if (err) {
throw err;
return res.status(400).send({
msg: err
});
}
return res.status(201).send({
msg: 'Registered!'
});
}
);
}
});
}
}
);
pool.end;
});
router.get('/secret-route', userMiddleware.isLoggedIn, (req, res, next) => {
console.log(req.userData);
res.send('This is the secret content. Only logged in users can see that!');
});
module.exports = router;
My Middleware users.js
module.exports = {
validateRegister: (req, res, next) => {
// username min length 3
if (!req.body.username || req.body.username.length < 3) {
return res.status(400).send({
msg: 'Passwort:' + req.body.username + 'Please enter a username with at least 3 chars',
});
}
// password min 6 chars
if (!req.body.password || req.body.password.length < 6) {
return res.status(400).send({
msg: 'Passwort:' + req.body.password + 'Please enter a password with at least 6 chars'
});
}
// password (repeat) does not match
if (
!req.body.password_repeat ||
req.body.password != req.body.password_repeat
) {
return res.status(400).send({
msg: 'Both passwords must match'
});
}
next();
},
isLoggedIn: (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
const decoded = jwt.verify(
token,
process.env.API_SecretKey
);
req.userData = decoded;
next();
} catch (err) {
return res.status(401).send({
msg: 'Your session is not valid!'
});
}
}
};
My index.js:
const express = require("express");
const DigitalMangement = express();
const cors = require('cors');
require("dotenv").config();
DigitalMangement.use(cors());
DigitalMangement.use(express.json());
// add routes
const router = require('./Routes/router.js');
DigitalMangement.use("/api", router);
DigitalMangement.listen(process.env.Application_Port, () => {
console.log("Server is running on Port " + process.env.Application_Port)
});
I haven't reviewed the whole code but, if you throw the error the code block will not continue. In this case, it won't be logged or sent as a response. Try removing the throw err line and rerun the code.
if (err) {
throw err; //! here
return res.status(400).send({
msg: err
});
}
Thanks for all the help fellow Coders:
It seems to be that the import MariaDB isn't 100% correct in this situation.
I changed it to mariadb/callback and it started to work.
The MariaDB library returns Promises and mariadb/callback allows callbacks.

TypeError: login.findOne(...).toArray is not a function

I have this function, whcih bascially gets the usernmae and password of the users input from the front-end form, and then checks it in mongodb:
app.post('/login', (req, res, next) => {
var username = req.body.username;
var password = req.body.password;
//connecting to the mongo client
client.connect().then (() => {
//defining database name and collection
const database = client.db("myFirstDatabase");
const login = database.collection("login");
//connecting to the mongo client
MongoClient.connect(uri, function(err, db) {
if (err) throw err;
//finding all documents inside array
login.findOne({"username": username}).toArray(function(err, result) {
if (err) throw err;
result.forEach(results =>
bcrypt.compare(password, results.password, function(err, result) {
if (result === true) {
req.session.loggedin = true
next()
} else {
res.redirect('/login')
}
})
);
db.close();
});
});
})
})
however, it is giving me this error:
TypeError: login.findOne(...).toArray is not a function
i've never encountered this error before. how do i fix this?
Try this way
login.findOne({"username": username}, function(err,user)
{ console.log(user); });

error 'user.findOneAndUpdate is not a function' but data updated

i'm trying to use findOneAndUpdate for change password on mongoose, it's work, database updated
but error message show
"error": "user.findOneAndUpdate is not a function"
this my routes
router.post('/changepass', async (req, res) => {
const { phone, password } = req.body;
try {
const user = await User.findOneAndUpdate({phone},{password})
await user.findOneAndUpdate();
res.send({ user });
} catch (err) {
console.log(err)
res.status(422).send({ error: err.message });
}
});
and this my userSchema
userSchema.pre('findOneAndUpdate', function(next) {
const update = this.getUpdate()
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(update.password, salt, (err, hash) => {
this.getUpdate().password = hash;
return next();
})
})
});
please help me, i'm stuck for hours on this
try removing this line await user.findOneAndUpdate(); This line is causing the error and as per official docs it should be not there
router.post('/changepass', async (req, res) => {
const { phone, password } = req.body;
try {
const user = await User.findOneAndUpdate({phone},{password})
res.send({ user });
} catch (err) {
console.log(err)
res.status(422).send({ error: err.message });
}
});
here is doc reference - https://mongoosejs.com/docs/tutorials/findoneandupdate.html

Data and salt arguments required

I'm trying to hash the password of admin in my site. I have searched and found out that this error is because of being null or undefined the value that we want to hash it.
here is my code, whenever I console.log(admin) it returns {}, I don't know why.
adminSchema.pre('save', (next) => {
var admin = this;
console.log(admin)
bcrypt.hash(admin.password, 10, (err, hash) => {
if (err) return next(err);
admin.password = hash;
next();
});
});
var adminModel = mongoose.model('Admin', adminSchema);
module.exports = adminModel;
server side code:
var adminModel = require('./../models/admins');
router.post('/register', (req, res) => {
var newAdmin = {
adminName: req.body.adminName,
faculty: req.body.faculty,
email: req.body.email,
password: req.body.password
}
adminModel.create(newAdmin, (err, admin) => {
if (err) {
console.log('[Admin Registration]: ' + err);
}
else {
console.log('[Admin Registration]: Done');
req.session.adminId = admin._id;
res.redirect('/admin/submitScore')
}
})
});
Unfortunately, I can't find the reason of that the console.log(admin) is empty. I would be thankful if anyone could help me.
The keyword this changes scope when used in arrow functions. See more here. This is not a problem in your express route, but in your mongoose middleware it is. Change your function to not use this or make an old fashioned function(){}

how to resolve data and hash error in node js bcrypt

Error: data and hash arguments required
i am doing simple, login signup and forgot password in node js using
bcrypt hash
code : for login
app.post('/login', (req, res) => {
console.log('login');
let {email, password} = req.body;
User.updateOne({email: email}, ' email password', (err, userData) => {
if (!err) {
let passwordCheck = bcrypt.compareSync(password, userData.password);
if (passwordCheck) {
console.log('login2');
req.session.user = {
email: userData.email,
id: userData._id
};
req.session.user.expires = new Date(Date.now() + 3 * 24 * 3600 * 1000);
res.status(200).send('You are logged in, Welcome!');
} else {
res.status(401).send('incorrect password');
console.log('login3');
}
} else {
res.status(401).send('invalid login credentials');
console.log('login4');
}
});
});
code for signUp :
app.post('/signup', (req, res) => {
let {email, password} = req.body;
let userData = {password: bcrypt.hashSync(password, 5, null), email };
console.log('out save');
let newUser = new User(userData);
newUser.save().then(error => {
if (!error) {
console.log('in save');
return res.status(200).json('signup successful');
} else {
if (error.code === 11000) {
return res.status(409).send('user already exist!');
} else {
console.log(JSON.stringigy(error, null, 2));
return res.status(500).send('error signing up user');
}
}
});
});
i have tried console logging few lines and turned out that the code doesn't go into signup
newUser.save();
tell me where i'm going wrong
The issue is with this line newUser.save().then(error => {. Do you notice the .then(). That is a resolved promise so it wouldn't be returning an error. Typically you would see something like this.
Promise()
.then((result) => {
// result is a resolved promise
})
.catch((error) => {
// error is a rejected promise
})
So you should try changing your code to this:
newUser.save()
.then(result => {
console.log('in save')
return res.status(200).json('signup successful')
})
.catch(error => {
if (error.code === 11000) {
return res.status(409).send('user already exist!')
} else {
console.log(JSON.stringigy(error, null, 2))
return res.status(500).send('error signing up user')
}
})
It looks like you're using mongoose, here is the API docs for Document.prototype.save() https://mongoosejs.com/docs/api.html#document_Document-save
Their documentation uses callback functions for the most part but if you scroll to the end of the .save() documentation you will see they show one example with a promise.
bcrypt.compareSync takes 2 parameters; passwordToCheck, passwordHash
You are getting error "bcrypt Error: data and hash arguments required"
This error means one or both parameters are either null or undefined,
In your case you need to make sure that password, userData.password are correctly going in function bcrypt.compareSync

Resources