The application works fine if the username or the password is incorrect.
But crashes if the username entered is correct and no password is entered.
This is the Error I'm getting before the app crashes:
Error: Illegal
arguments: undefined, string at _async
user.js
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, (err, isMatch) =>{
if(err) throw err;
callback(null, isMatch);
});
}
users.js:
router.post('/authenticate/user', (req, res, next) =>{
const username = req.body.username;
const password = req.body.password;
User.getUserByUsername(username, (err, user) => {
if(err) throw err;
if(!user){
return res.json({success: false, msg: 'User Not Registered'});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch){
const token = jwt.sign({data: user}, config.secret, {
expiresIn : '6h'
});
res.json({
success: true,
token: 'JWT ' +token,
user:{
id: user._id,
username : user.username
}
});
} else {
return res.json({success: false, msg: 'Wrong Password'});
}
});
});
});
Should I add validation on the front-end of the application for a quick fix or is that not a good idea?
Thanks in advance.
Simple fix would be to check "candidatePassword" before comparing to hash and if it is empty throw an error.
Related
I implemented a signup route below. It gets to "User saved..." but the request returns 404.
It doesn't seem to be executing the login strategy:
router.post("/signup", function(req, res, next) {
var email = req.body.email;
var password = req.body.password;
User.findOne({ email: email }, function(err, user) {
if (err) { return next(err); }
if (user) {
return res.status(409).send({message: "Duplicate user - already registered."});
}
var newUser = new User({
email: email,
password: password
});
newUser.save(next);
console.log("User saved...");
});
},
passport.authenticate("login"),
function(req, res) {
return res.status(200).send({
message: "Signup successful",
user: req.user
});
}
);
My Passport login strategy looks like this:
passport.use("login", new LocalStrategy(async (email, password, done) => {
console.log("login...");
User.findOne({ email: email }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: "No user has that email!" });
}
user.checkPassword(password, function(err, isMatch) {
console.log("Checked password...");
console.log("Error? Match?");
console.log(err);
console.log(isMatch);
if (err) { return done(err); }
if (isMatch) {
console.log("Returning done...");
return done(null, user, { message: 'Logged in Successfully' });
} else {
return done(null, false, { message: "Invalid password." });
}
});
});
}));
Here's what I see in the logs:
User saved...
POST /signup 400 181.122 ms - -
Passport is likely throwing the 400 error because the username/password fields are not set.
Passport expects username and password and what you are passing are the email and password. So you can modify the code and let passport's LocalStrategy use the email as the username.
You can set the username and password as follows:
passport.use("login", new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
},async (usernameField, passwordField, done) => {
console.log("login...");
User.findOne({ email: usernameField }, function (err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: "No user has that email!" });
}
user.checkPassword(passwordField, function (err, isMatch) {
console.log("Checked password...");
console.log("Error? Match?");
console.log(err);
console.log(isMatch);
if (err) { return done(err); }
if (isMatch) {
console.log("Returning done...");
return done(null, user, { message: 'Logged in Successfully' });
} else {
return done(null, false, { message: "Invalid password." });
}
});
});
}));
You can check the line which was throwing the error from passport's source code here
I am trying to login but the below code always returning below error though the email and password is correct
Authentication failed! Incorrect Password!
exports.login = (req, res, next) => {
User.findOne({
email: req.body.email
}, (err, user) => {
if (err) throw err;
if (!user) {
res.status(401).json({ authenticated: false, message: 'Email is not registered yet! Please Signup and try Signin' });
} else {
// Check if password matches
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch) return res.status(401).send({ message: 'Authentication failed! Incorrect Password!' });
// Make sure the user has been verified
if (!user.isVerified) return res.status(401).send({ type: 'not-verified', message: 'Your account has not been verified. Please check your email' });
if (isMatch) {
const userInfo = setUserInfo(user);
console.log("userInfo: ", userInfo)
res.status(200).json({
token: `${generateToken(userInfo)}`,
user: userInfo
});
}
});
}
});
};
Any idea what I am doing wrong.
This is my passport Login Handler.
Now I want to send JSON Data under every condition so that API can access the response and on behalf of this display anything on frontend.
//Login Handler
passport.use('local-user', new LocalStrategy(
function(username, password, done) {
User.getUserByUsername(username, function(err, user){
if(err) {
console.log('error')
logger.log('error', 'Error Generates on User.getUserByUsername Query on users.js file');
throw err;
}
if(!user){
//res.send('unknown user');
console.log('Unknown User');
return done(null, false, {message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) {
logger.log('error', 'Error Generates on User.comparePassword Query on users.js file');
throw err;
}
if(isMatch){
return done(null, user);
}else{
return done(null, false, {message: 'Invalid Credential, please check carefully...!'})
}
});
});
}
));
Anyone have any idea for this? Thanks in advance
The local strategy will pass the user or error with done(), then you receive that with a callback and pack it with res.json()
Here is my implementation. May help?
passport.use(
new LocalStrategy(
{
usernameField: "email"
},
function(username, password, done) {
User.findOne({ email: username }, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {
email: "Email not found"
});
}
if (!user.validPassword(password)) {
return done(null, false, {
password: "Password is wrong"
});
}
return done(null, user);
});
}
)
);
router.post("/login", function(req, res) {
passport.authenticate("local", function(err, user, info) {
if (err) {
res.status(404).json(err);
return;
}
if (user) {
const token = user.generateJwt();
res.status(200);
res.json({
userInfo: user,
token: token
});
} else {
res.status(401).json(info);
}
})(req, res);
});
I have a problem with my code. When I am trying to login without insert username and password
POST /user/login 302 1.289 ms - 32
GET /user/hehehehehe 404 6.310 ms - 1272
If i try to login with only login it's the same result
If i try to login with username and password correct or incorrect
500 Internal Server Error
Can someone tell me, where the mistake is?? That is first load failureRedirect. What is first thing I should check after trying to login??
router.post('/create', function (req, res, next) {
var newUser = {
username: req.body.username,
password: req.body.password
}
console.log(req.body)
req.checkBody('username', 'Login is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
var errors = req.validationErrors();
if (errors) {
console.log(errors)
res.send(errors);
} else {
bcrypt.hash(newUser.password, saltRounds, function (err, hash) {
if (err) {
console.log(err)
} else {
newUser.password = hash;
var user = new User(newUser);
user.save()
.then(function (User) {
res.send(User);
})
}
});
req.flash('success_msg', 'You are registered and can now login');
//res.redirect('/');
}
});
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) {
console.log('eheheheheh');
done(null, user.id);
});
passport.deserializeUser( function(id, done) {
User.getUserById(id, function(err, user) {
console.log('eheheheheh');
done(err, user);
});
});
router.post('/login',
passport.authenticate('local', { successRedirect:'hahahha', failureRedirect:'hehehehehe', failureFlash: true }),
function(req, res) {
console.log('yyy'),
res.redirect('dydydydy');
});
IMPORTANT
Which functions are loaded first?
1 - /login
Then this code?
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'});
}
});
});
}));
What mistakes might be here??
Whenever I try to login a user through a post request in Postman, I keep getting this error:
Here is the localStrategy I made for checking if a user's email and password can be verified:
passport.use(new LocalStrategy({usernameField: 'email', passwordField: 'password'}, function(email, password, done){
User.findOne({email: email}, (err, user) => {
if (err) return done(err);
if (!user){
return done(null, false, {message: "User is not registered"});
}
else {
const realPassword = String(user.password);
bcrypt.compare(password, realPassword, (err, result) => {
if (err) throw err;
if (result){
console.log('result is...' + result);
done(null, user)
}
else {
console.log('result is...' + result);
return done(null, false, {message: 'Invalid Password'});
}
}
});
}));
And here is the post request method in my router file:
router.post('/login', passport.authenticate('local', {session: false}), (req, res, next) => {
function generateUserToken(user){
return jwt.sign({sub: user._id, creationDate: user.creationDate}, config.secretKey);
}
if (err) throw err;
res.send({token: generateUserToken(user)})
});
UPDATE: I changed some of my code now to address issues raised. However, now instead of getting unauthorized, I keep getting a 404 not found error
In my case there where dismatch in findOne(), User schema has local.email, so I needed to search for findOne({'local.email': email}, ...).
Seems the value of doesMatch is always false.
I believe you're missing the bcrypt.compare doesn't return anything.
It is asynchronous, so, you can't get the result using the return statement.
You have to put everygint inside of the callback function from bcrypt.compare
bcrypt.compare(password, realPassword, (err, result) => {
if (err) throw err;
// NOW YOU HAVE THE VALUE FORM THE COMPARISON
if (result){
done(null, user)
}
else {
return done(null, false, {message: 'Invalid Password'});
}
});
Let me know if it works.
Hope it helps you.