Verify Email Before Logging In (Nodejs, Mongoose+mongodb, Passportjs) - javascript

I'm having a problem about verifying first my email address before i can login to my system . Here's my code so far.
This line of code is where i verify my email address when he clicks the link on his/her email address it will redirect to my login form.
router.get('/verify_email', function(req, res){
console.log('verify_email token: ', req.query.token);
User.findOne({authToken: req.query.token}, function(err, user){
if(err){
console.log(err);
} else {
console.log(user);
user.IsAuthenticated = true;
user.save(function(err){
if(err){
console.log(err);
} else {
console.log('Successfully updated user');
console.log(user);
sendgrid({
to: user.email,
from: 'pektospioneers.com',
subject:'Email COnfirmed!',
html: 'Thank you'
}, function(err, json){
if(err){
console.log(err);
} else {
console.log(json);
}
});
res.send(user);
}
});
}
});
req.flash("success_msg",'Email has been confirmed!');
res.redirect('/users/login');
});
and here's my usermodel
//new user in the model(user.js)
var newUser = new User({
name: name,
email: email,
authToken: authToken,
IsAuthenticated: false,
username: username,
password: password,
field: field,
e_money: e_money //temporary emoney
});
now the problem is here . I can still login directly after my registration even without confirming my email . so what should be the problem here sir/madame .
i tried the passportjs like this
passport.use(new LocalStrategy(
function(username, password, IsAuthenticated, done){
User.IfIsAuthenticated(IsAuthenticated, function(err, authenticated)}
if(err) throw err;
if(!authenticated){
return done(null, false, {message: 'Please confirm your email first'});
}
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"});
}
});
});
});
}));
but its not working it always says return done is not a function
and on my user.js it's just like this
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
/*
*need to know if authenticated or not
*so that if it is not yet authenticated
*the newly registered user cannot logged in
*/
module.exports.ifIsAuthenticated = function(IsAuthenticated, callback){
var query = {IsAuthenticated:IsAuthenticated};
User.findOne(query, callback);
}

By adding here this line of code i achieved what i want
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch && !User.email){
return done(null, false, {message: "Please confirm your email first!"});
}else if(isMatch && User.email){
return done(null, user);
}
else{
return done(null, false, {message: "Invalid password"});
}
});
Just need to answer this for the future reference of the others . Happy coding

Related

bcryptjs compare function returns false when passwords contain numbers

I have used bcryptjs to hash my passwords and the registration of the user takes place fine.
But when I try to login, the bcrypt.compare function returns a false promise if the passwords contain numbers or other characters.
Everything works fine if the password is just letters.
I have searched everywhere but could not find a solution for this error?
Here are my files :
users.js (MODEL)
var mongoose = require("mongoose");
var bcrypt = require("bcryptjs");
var userSchema = mongoose.Schema({
name: String,
email: String,
password: String,
products: [{
type: mongoose.Schema.Types.ObjectID,
ref: "Product"
}],
username: String
});
var User = module.exports = mongoose.model("User", userSchema);
module.exports.createUser = function(newUser, callback) {
bcrypt.genSalt(5,function(err,salt){
bcrypt.hash(newUser.password,salt,function(err,hash){
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
console.log(isMatch);
callback(null, isMatch);
});
}
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
app.js
app.use(passport.initialize());
app.use(passport.session());
var LocalStrategy = require("passport-local").Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({username: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) {
console.log("ERR1");
return done(err);
}
if(isMatch) {
console.log("MATCH");
return done(null,user);
} else {
console.log("NOT VALID");
return done(null, false, {message: 'Invalid password'});
}
});
});
}
));
passport.serializeUser(function(user,done){
done(null,user.id);
});
passport.deserializeUser(function(id,done){
User.getUserById(id, function(err,user){
done(err,user);
})
})
users.js (ROUTE)
router.post("/login", passport.authenticate('local', function (error, user, info){
if(error) {
console.error(error);
console.log('Failed login:');
}
if (user === false) {
console.log("user not found");
} else {
// handle successful login ...
console.log("logged in");
}
}), function (req, res) {
res.send(req.user);
});
router.post("/signup", function (req, res) {
console.log(req.body);
var password = req.body.password;
var password2 = req.body.password2;
if(password == password2) {
var newUser = new User ({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.username
});
User.createUser(newUser, function(err, user){
if(err)
throw err;
console.log(user);
res.send(user).end();
});
} else {
res.status(500).send("{errors: \"Passwords don't match\"}").end()
}
});
Whenever I enter a password that contains numbers, I get
false
NOT VALID
user not found
I'm sorry if I have done or not done something extremely simple. This is my first time using bcryptjs.
All answers are appreciated!
In the users.js file at the comparePassword function inside the compare method of bcrypt you are throwing the error instead of passing it to the callback. Maybe if you make this change:
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
console.log(isMatch);
callback(err, isMatch);
});
}
You will see what kind of error it's generated by the case when you introduce numbers in your passwords.

"req.checkBody is not a function"?

When I submit a form whose contents are validated using express-validator I keep getting the error "req.checkBody is not a function" (and if I remove the line that generates that, I get other errors, like "req.sanitize is not a function"). It seems that express-validator is not being recognized properly so i thought of changing the current version and then I have uninstalled the current version and installed an older version#5.3.1 still It is showing the same error.
first I have required it in the main app.js file
var validator = require('express-validator');
Then I have used it like this for validation purpose
var User = require('../models/admin');
var LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local.signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
}, function(req, email, password, done) {
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty().isLength({min:4});
var errors = req.validationErrors();
if (errors) {
var message = [];
errors.forEach(function(error){
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({'email' : email}, function(err, user) {
if (err){
return done(err);
}
if (user){
return done(null, false, {message: 'email is already in use'});
}
var newUser = new User();
newUser.email = email;
newUser.password = newUser.encryptPassword(password);
newUser.save(function(err, result) {
if (err) {
return done(err);
}
return done(null, newUser);
});
});
}));
passport.use('local.signin', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
},function (req, email, password, done){
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty();
var errors = req.validationErrors();
if (errors) {
var message = [];
errors.forEach(function(error){
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({'email' : email}, function(err, user) {
if (err){
return done(err);
}
if (!user){
return done(null, false, {message: 'No user found!!'});
}
if (!user.validPassword(password)){
return done(null, false, {message: 'Wrong password!!'});
}
return done (null, user);
});
}));```

Bcrypt not encrypting the password in Node JS

I am trying to make a user account system in node and am using bcrypt for hashing passwords. My syntax seems to be correct, and there is no error thrown in the console, however still the passwords aren't getting encrypted when stored in the database(mongo db).
This is my user.js file in models:
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');
mongoose.connect('mongodb://localhost/nodeauth');
var db = mongoose.connection;
// User
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String,
required: true,
bcrypt: true
},
email: {
type: String
},
name: {
type: String
},
profileImage: {
type: String
}
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.comparePassword = function(candidatePassword, hash, callback) {
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) return callback(err);
callback(null, isMatch);
});
}
module.exports.getUserById = function(id, callback) {
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback) {
var query = {username: username};
User.findOne(query, function(err, user) {
callback(err, user);
});
}
module.exports.createUser = function(newUser, callback) {
bcrypt.hash(newUser.password, 10, function(err, hash) {
if(err) throw err;
// Set hashed password
newUser.password = hash;
// Create user
newUser.save(callback);
});
}
And this is the relevant part of users.js file in routes which is used in the login section to check whether the username and password match(which is also not working):
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy(function(username, password, done) {
User.getUserByUsername(username, function(err, user) {
if(err) throw err;
if(!user) {
console.log('Unknown 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 {
console.log('Invalid Password');
return done(null, false, {message: 'Invalid Password'});
}
});
});
}));
router.post('/login', passport.authenticate('local', {successRedirect: '/', failureRedirect:'/users/login', failureFlash:'Invalid username or password'}), function(req, res) {
console.log('Authentication Successful');
req.flash('success', 'You are logged in');
res.redirect('/');
});
module.exports = router;
I am not able to understand why the passwords aren't getting encrypted, and even then, why is comparePassword always returning a failure, thus making authentication fail every time as well.
Is there anything I am missing?

Sails + passport + Basic Authentication

in passport js, basic strategy, the following code sample provides a function for verifying the identity of a user.
passport.use(new BasicStrategy(
function(userid, password, done) {
User.findOne({ username: userid }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
Question is where (which file) in a Sails application should this code be placed? I suppose same applies for a custom verification function?
create AuthController under controllers directory
then write code to make passport handle login process
login: function(req, res) {
passport.authenticate('local', function(err, user, info) {
if ((err) || (!user)) {
return res.send({
message: info.message,
user: user
});
}
req.logIn(user, function(err) {
if (err) res.send(err);
return res.send({
message: info.message,
user: user
});
});
})(req, res);
this line passport.authenticate('local' will read configuration from passport.js inside config.js which will be like this :-
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function(email, password, done) {
User.findOne({ email: email }, function (err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect email.' });
}
bcrypt.compare(password, user.password, function (err, res) {
if (!res)
return done(null, false, {
message: 'Invalid Password'
});
var returnUser = {
email: user.email,
createdAt: user.createdAt,
id: user.id
};
return done(null, returnUser, {
message: 'Logged In Successfully'
});
});
});
add these line into route.js :- 'post /login': 'AuthController.login'

Nodejs - Passport authenticate always return failure redirect

I'm making a form login by passportJs and it always return failureRedirect. I have search in stack overflow for this issue, but still not have the correct answer. Here is my code:
Form making form jade:
form(method='post', action='/users/login', enctype='multipart/form-data')
.form-group
label Username
input.form-control(name='username', type='text' placeholder='Enter Username')
.form-group
label Password
input.form-control(name='password', type='password' placeholder='Enter password')
input.btn.btn-default(name='submit', type='submit', value='Login')
Router Hanlde is using express framework form Nodejs and passport middleware:
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done) {
User.getUserByUsername(username, function(err, user) {
if (err) throw err;
if (!user) {
console.log('Unknown 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 {
console.log('Invalid Password');
return done(null, false, {
message: 'Invalid Password'
});
}
});
});
}
));
router.post('/login', passport.authenticate('local', {
failureRedirect: '/users/login',
failureFlash: 'Invalid username or password'
}), function(req, res) {
console.log('Authentication Successful');
req.flash('success', 'You are logged in ');
res.redirect('/');
});
Looking at getUserByUsername function you shared in comments, it looks like you are not making call to callback function of getUserByUsername in correct way and therefore it is not getting user object resulting into failure redirect. The function you shared was:
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, callback);
}
Changing it to following should fix your issue:
module.exports.getUserByUsername = function(username, callback){
var query = {username: username};
User.findOne(query, function(err, user) {
callback(err, user);
});
}

Categories

Resources