(Assume the hashing has been done) I am trying to do an authenticate user function, by comparing an entered password and its hash in my MongoDB collection. This is my the method in my model.js (copied from the bcrypt guide):
PetOwnerSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
And my controller.js:
exports.check = function (req, res) {
var email = req.body['email'];
var password = req.body['password'];
PetOwner.findOne({ "email" : email}, 'email', function(err, task) {
if (err)
res.send(err);
if ( task === null ){
res.json(0); // no matching result
console.log("Email is not yet registered");
} else {
task.comparePassword(password, task.password, function(err, isMatch) { //compare password and the already-hashed password in MongoDB
if (err) throw err;
if(isMatch){
res.json(1);
console.log("Found matching password to email");
}
else{
res.json(0);
console.log("Wrong password");
}
});
}
})
};
And when I fetch the check method, the node console prompts the error that the cb in my model.js is not a function. I have tried several workaround but none has worked so far. Is there any way to debug this?
PetOwnerSchema.methods.comparePassword = function(candidatePassword, cb)
Your function takes a single parameter so you cannot refer to a context of "this" outside the function, like you do by using "this.password".
If you add the password to compare with as a second parameter like so:
PetOwnerSchema.methods.comparePassword = function(candidatePassword, password2, cb)
You can then just compare the two inside the function as you are trying to do.
Hope it helps
Related
I'm creating a simple api witch verify if the username and/or password are in the DB and if they are correct.
When I post correct data, it works. When I post a wrong password, it also works. But when I post a wrong username, my condition don't jump to the else. If the username is wrong, it means it is not in the DB. But here, it is like if it was in the DB, but he is not, so I get an error : " TypeError: Cannot read properties of undefined (reading 'Username') "
Here the code
app.post('/login', function(req, res) {
(async () => {
const bcrypt = require('bcrypt')
try {
username = req.query.username
password = req.query.password
let salt = await bcrypt.genSalt(10)
let hash = await bcrypt.hash(password, salt)
db_conn.getConnection( (err, conn) => {
if(err) throw err;
conn.query("SELECT * FROM mod803_appusers WHERE Username=? ", [username], (err, rows) => {
//Problem here : when I put a wrong password, it's ok, this condition works because there is a password, and if bcrypt.compare is true, it sends response, but if it's false, it sends 'Wrong password'.
//But if the Username is Wrong, it means there is no username in the DB. So here, I want this condition jump to the else : 'Incorrect username' but it doesn't.
if(rows[0]['Username'] && rows[0]['Password']) {
bcrypt.compare(password, rows[0]['Password'], function(err, result) {
if(result){
res.send({"table": rows});
} else {
res.send("Wrong password");
}});
} else {
res.send('Incorrect username');
}
})
})
} catch (error) {
console.log(error.message)
}
})()
})
Thanks
I'm trying to connect my Mongodb with Auth0 authorization. I'm using Mlabs to host my db. Inside this db, I have a "users" collection, and the documents have "username", "password", "email, and "_id" keys. When I try to use the Auth0 login script, I get the following error: Not authorized for query on mydb.users. Below is the script:
function login(email, password, callback) {
mongo('<mongodb uri>', function (db) {
var users = db.collection('users');
console.log(users);
users.findOne({ email: email }, function (err, user) {
if (err) return callback(err);
if (!user) return callback(new WrongUsernameOrPasswordError(email));
bcrypt.compare(password, user.password, function (err, isValid) {
if (err) {
callback(err);
} else if (!isValid) {
callback(new WrongUsernameOrPasswordError(email));
} else {
callback(null, {
user_id: user._id.toString(),
nickname: user.nickname,
email: user.email
});
}
});
});
});
}
Any ideas why I might be getting this error? Thanks in advance!
You probably have to check for a connection to the db.
The callback should have an error parameter
mongo('<mongodb uri>', function (err,db) {
if(err){
console.log(err)
}
})
if that doesn't fix it then you have to assign read and write permissions to perform the intended operations (in your case read) on the specified database
I'm trying to make my code cleaner in that seperating functions into other files. Namely, I have a UsersController.js that will perform functions on the Users database. With only one function inside right now...
var User = require('../user/User');
module.exports = function(){
this.verifyNoExistingUser = function verifyNoExistingUser(email, name){
//check if email is taken
User.findOne({email: email}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
//check if username is taken
User.findOne({name: name}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
return true;
}
});
}
return false;
});
}
};
Then when I go to use it in my app.js, like such....
var express = require('express');
var router = express.Router();
...
var UsersController = require('../user/UsersController.js');
...
router.post('/register', function(req, res){
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
if(!UsersController.verifyNoExistingUser(req.body.email, req.body.name)){
console.log(val);
return res.status(500).send("Username or email already exists.");
}
I'm getting that my function is not a function. When I call...
UsersController.verifyNoExistingUser(req.body.email, req.body.name)
I was specifically trying to follow this SO question but not getting a correct result. Any help on how to include functions from other JS files?
In your top file, you're exporting a function:
module.exports = function(){
In your bottom file, you're importing the function:
var UsersController = require('../user/UsersController.js');
and trying to access one if its properties:
if(!UsersController.verifyNoExistingUser...
which of course doesn't exist. Assigning to a this inside a function doesn't assign to the function's properties itself, and even if it did, you would have to run the function first for the property to be assigned.
If you want to consume it like that, you should export an object instead:
var User = require('../user/User');
module.exports = {
verifyNoExistingUser: function verifyNoExistingUser(email, name){
//check if email is taken
User.findOne({email: email}, function(err, user){
// ...
But if verifyNoExistingUser is the only function you want to export, then why not export it directly, rather than export an object?
module.exports = function verifyNoExistingUser(email, name){
You have defined as function and calling as object, you can either call function as following
var UsersController = require('../user/UsersController.js')();
or define as object
var User = require('../user/User');
module.exports = {
this.verifyNoExistingUser = function verifyNoExistingUser(email, name){
}
};
Why you don't simply write:
module.exports = (email, name){
//check if email is taken
User.findOne({email: email}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
//check if username is taken
User.findOne({name: name}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
return true;
}
});
}
return false;
});
};
Then in the another file:
var verifyNoExistingUser = require('../user/UsersController.js');
(you may rename UsersController.js to verifyNoExistingUser.js
And call it:
verifyNoExistingUser(req.body.email, req.body.name)
You can do something like this:
var User = require('../user/User');
function verifyNoExistingUser(email, name){
//check if email is taken
User.findOne({email: email}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
//check if username is taken
User.findOne({name: name}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
return true;
}
});
}
return false;
});
}
module.exports = {
verifyNoExistingUser,
}
try
module.exports = {
verifyNoExistingUser: function (email, name){
//check if email is taken
User.findOne({email: email}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
//check if username is taken
User.findOne({name: name}, function(err, user){
if(err){
return res.status(500).send('Error on the server.');
}
if(!user){
return true;
}
});
}
return false;
});
}
};
I need help to figure this out. The update function is called to reset a password on database. I got this error.
TypeError: Cannot read property 'password' of undefined
module.exports.update = function (token, req, res) {
User.findOneAndUpdate({resetPasswordToken: token, password: req.body.password, resetPasswordExpires: {$gt: Date.now()}}, function(err) {
if (err) throw err;
return res.sendStatus(200);
console.log(User);
});
}
router.post('/forgot', function (req, res) {
var password = req.body.passwordnew;
var password2 = req.body.passwordnew2;
var update = User.update(password, password2, function (err, user) {
//userToken = token;
if (!update) {
console.log("token2 = " + req.params.resetPasswordToken);
req.flash('error', 'Password reset token is invalid or has expired.');
return res.redirect('forgot');
}
else {
user.save(function (err) {
user.password = password;
user.password2 = password2;
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
});
console.log("save new password");
}
});
//}
})
when you use update method of mongoose 1st parameter will be query( by which you can find that doccument in collection) and 2nd will be what you want to update ..
So what query you make is not make sense , it will be like :
var userId=user; //mongoId
var newPassWord=req.body.passwordnew;
User.update({_id:userId}, {password:newPassWord}, callbackFunction);
this will update password of that perticular user.
Thanks
I want to have login/register function in my expressJS API.
So now im just inserting password and email into my database, i want this function to first check if user with this email is already in database - if yes, send response that user is logged.
If not, just insert him to database.
Is it possible to handle some errors in here?
I already have it:
exports.login = function(req, res){
var email = req.body.email;
var pwd = req.body.pass;
db.collection('users', function(err, collection) {
collection.insert({login:email, password: pwd}, {safe:true}, function(err, result) {
res.send("OK");
});
});
};\
and dont know what's next.
You can first try to find the user in your database. Assuming email is unique;
exports.login = function(req, res){
var email = req.body.email;
var pwd = req.body.pass;
db.collection('users', function(err, collection) {
if (err) return res.send(500, err);
collection.findOne({login:email}, function(err, user) {
// we found a user so respond back accordingly
if (user) return res.send('user logged in');
collection.insert({login:email, password: pwd}, {safe:true}, function(err, result) {
if (err) return res.send(500, err);
res.send("OK");
});
});
});
};
notice the return's before the res.send calls when handling errors.