Using promises in mongoose for passport authentication - node.js

var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
module.exports = function(passport){
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
User.findOne({'local.username': email}).exec()
.then(function(user) {
console.log(user);
if(user){
return done(null, false, {message: 'Username already taken!'});
}
else{
var newUser = new User();
newUser.local.username = email;
newUser.local.password = password;
return newUser.save();
}
})
.then(function(user) {
console.log('DEBUG DEBUG DEBUG');
done(null, user);
})
.catch(function(err) {
done(err);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(userid, done) {
User.findById(userid).exec()
.then(function(user) {
done(user);
});
});
};
In my case the debug log always be printed, whether return newUser.save() is called or not.
Is it possible to make the debug log only be printed when return newUser.save() is called?
Btw I'm using passportJS for authentication things and for the promise I'm override mongoose default promise with global es6 promise.

You mean like this? Sorry if there are extra brackets or parenthesis. I edited in the text box. :(
User.findOne({'local.username': email}).exec()
.then(function(user) {
if(user){
return done(null, false, {message: 'Username already taken!'});
}
else{
var newUser = new User();
newUser.local.username = email;
newUser.local.password = password;
return newUser.save()
.then(function(){
console.log('DEBUG DEBUG DEBUG');
done(null, user);
})
}
})
.catch(function(err) {
done(err);
});
}
));

Just put your debug message in a function in newUser.save()
User.findOne({'local.username': email}).exec()
.then(function(user) {
console.log(user);
if(user){
return done(null, false, {message: 'Username already taken!'});
}
else{
var newUser = new User();
newUser.local.username = email;
newUser.local.password = password;
return newUser.save(function() {
console.log('SAVED!');
console.log('DEBUG DEBUG DEBUG');
});
}
})
.then(function(user) {
done(null, user);
})

Related

I'm trying to implement passport-local but i'm getting error

This is the error I'm getting in passport.js config. I don't understand what it means: Why passport.use is not a function?
TypeError: passport.use is not a function
This is my code:
const LocalStrategy = require('passport-local').Strategy;
const passport = require('passport');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// load user models
const User = require('../models/Users');
module.exports = function (passport) {
passport.use (
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
// Match User
User.findOne({ email: email })
.then((user) => {
if (!user) {
return done(null, false, { message: 'Email is not registered' })
}
})
.catch((err) => {
console.log(err);
})
// match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw (err)
if (isMatch) {
return done(null, user)
} else {
return done(null, false, { message: 'Incorrect Password' })
}
})
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser( (id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
passport.js
const passport = require("passport")
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
// Local Strategy
passport.use(new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
try {
// find the user given the email
const user = await User.findOne({ "email": email });
// if not, handle it
if (!user) {
return done(null, false);
}
// check if password is correct
const isMatch = await user.isValidPassword(password);
// if not handle it
if (!isMatch) {
return done(null, false);
}
// otherwise return the user
done(null, user);
} catch (error) {
done(error, false);
}
}));

Password validation in nodejs using passport js

I'm using passport js local strategy for authentication and nodejs. problem is when i try to login with wrong password, I still redirects to success page.
what i have to do
this is login strategy
const passport = require('passport')
const LocalStratery = require('passport-local').Strategy;
const User = require('../models/userAuth')
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local-login', new LocalStratery({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done) {
console.log(email)
console.log(password)
User.findOne({email: email})
.then((err, user) => {
if(err) {
return done(null, err, req.flash('unkonown', 'there was an error,
please try after sometime'))
}
if(!user) {
console.log(user)
return done(null, false, req.flash('NotExists', 'no user
exixts'))
}
if(!user.validpass(password)){
return done(null, false, req.flash('passFail', 'password not
matches'))
}
if(user) {
return done(null, user, req.flash('success', 'login success'))
}
})
.catch(err => {
throw err
})
}))
user model using mongoose
userAuth.methods.excryptPass = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null)
}
userAuth.methods.validpass = (password) => {
return bcrypt.compareSync(password, this.password);
}

Uncaught, unspecified "error" event. (Incorrect arguments) in passport [Node.js]

I have used passport for validation and saved the values is resource collection , and am getting Uncaught, unspecified "error" event. (Incorrect arguments). But i have used the same name of email and password only
My passport.js in following
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var User = require('../app/models/db_model');
module.exports =function(passport){
passport.serializeUser(function(user, done) {
done(null, user.id);
//console.log("ser"+user);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
//console.log("deser"+user);
done(err, user);
});
});
passport.use('local-userlogin', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'email' : email}, function(err, user) {
console.log(user);
if (err)
return done(err);
if (!user)
return done(null, false, req.flash('loginMessage', 'Oops! Invalid Username.'));
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Invalid Password.'));
return done(null, user);
});
}));
}
Kindly help me in this issue
I received the same error when using Passport with Bcrypt [bcrypt-nodejs].
In my user model I had
userSchema.methods.encryptPassword = password => {
return bcrypt.hashSync(password, bcrypt.genSaltSync(1), null);
}
userSchema.methods.validPassword = password => {
return bcrypt.compareSync(password, this.password);
}
Which I then replaced with
userSchema.methods.encryptPassword = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null);
}
userSchema.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
}
And that got rid of the error.
This seems to imply that bcrypt-nodejs does not like arrow functions.
Hope this helped.

User Authentication on MEAN stack application

I am building an API using the MEAN stack and am working on the login and signup functions.
And I want to respond with a json string as follows
{
success: 0,
message: ""
}
success:1 for successful login and 0 otherwise.
My authenticate.js is as follows
module.exports = function(passport){
//log in
router.post('/login', passport.authenticate('login', {
//success
//failure
}));
//sign up
router.post('/signup', passport.authenticate('signup', {
//success
//failure
}));
//log out
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/');
});
return router;
}
My passport.init.js middleware is as follows
var mongoose = require('mongoose');
var User = mongoose.model('User');
var LocalStrategy = require('passport-local').Strategy;
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport){
// Passport needs to be able to serialize and deserialize users to support persistent login sessions
passport.serializeUser(function(user, done) {
console.log('serializing user:',user.username);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
console.log('deserializing user:',user.username);
done(err, user);
});
});
passport.use('login', new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
// check in mongo if a user with username exists or not
User.findOne({ 'username' : username },
function(err, user) {
// In case of any error, return using the done method
if (err)
return done(err);
// Username does not exist, log the error and redirect back
if (!user){
console.log('User Not Found with username '+username);
return done(null, false);
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false); // redirect back to login page
}
// User and password both match, return user from done method
// which will be treated like success
return done(null, user);
}
);
}
));
passport.use('signup', new LocalStrategy({
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
// find a user in mongo with provided username
User.findOne({ 'username' : username }, function(err, user) {
// In case of any error, return using the done method
if (err){
console.log('Error in SignUp: '+err);
return done(err);
}
// already exists
if (user) {
console.log('User already exists with username: '+username);
return done(null, false);
} else {
// if there is no user, create the user
var newUser = new User();
// set the user's local credentials
newUser.username = username;
newUser.password = createHash(password);
// save the user
newUser.save(function(err) {
if (err){
console.log('Error in Saving user: '+err);
throw err;
}
console.log(newUser.username + ' Registration succesful');
return done(null, newUser);
});
}
});
})
);
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
};
// Generates hash using bCrypt
var createHash = function(password){
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
};
};
Please help me out in passing the JSON string accordingly
Using Express, all you have to do is to execute res.json inside any controller, passing it any JavaScript object. Express will automatically convert it to JSON and return it to the user.
return res.json({ success: 0, message: '' }

How to disable serializeuser and deserializeuser for specific strategy

I have code like this:
passport.serializeUser(function (user, done) {
console.log('serializing user ' +user._id);
return done(null, user._id);
});
passport.deserializeUser(function (id, done) {
console.log(id);
Users.findById(id, function (err, user) {
console.log('deserialize user ' +id);
done(err, user);
});
});
passport.use('login', new LocalStrategy({
passReqToCallback: true
},
function (req, username, password, done) {
Users.findOne({username: username}, function (err, user) {
if(err){
return done(err);
}
if(!user){
console.log('User Not Found with username '+username);
return done(null, false);
}
if(!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false); // redirect back to login page
}
return done(null, user);
}
);
})
);
passport.use('signup', new LocalStrategy({
passReqToCallback: true
},
function (req, username, password, done) {
Users.findOne({username: username}, function (err, user) {
if(err){
return done(err);
}
if(user){
console.log('User already exists with username: '+username);
return done('User already exists', false);
}
else{
var newUser = new Users();
newUser.username = username;
newUser.password = createHash(password);
newUser.save(function (err) {
if(err){
console.log('Error in Saving user: '+err);
throw err;
}
console.log(newUser.username +' Registered Successfully');
return done(null, newUser);
});
}
});
})
);
var isValidPassword = function (user, password){
return bCrypt.compareSync(password, user.password);
};
var createHash = function (password){
return bCrypt.hashSync(password,bCrypt.genSaltSync(10), null);
};
The problem is, when client sign-up new user and registered successfully. client will be automatically authenticated.
How to make client is still not authenticated until he/she is log-in??
So the flow I want is:
1. client register new ID
2. Client still not authenticated until he/she is login
3. client login
4. Client is authenticated now

Resources