Passport LocaStrategy signup redirect issue - javascript

I am trying to redirect user after signup on Passport
passport.use('local-signup', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true},
function(req, username, password, done) {
// asynchronous
// User.findOne wont fire unless data is sent back
process.nextTick(function() {
// find a user whose username is the same as the forms username
User.findOne({ username : username }, function(err, user) {
// if there are any errors, return the error
if (err)
return done(err);
if (user) {
return done(null, false, req.flash('signupMessage', 'Username is already taken.'));
} else {
var newUser = new User();
newUser.username = username;
newUser.password = password;
newUser.email = req.body.email;
newUser.save(function(err) { // create user
if (err) {
return next(err);
} else {
var site = new Site({user : newUser.username, siteTitle: newUser.username});
site.save(function(err) { // create website
if (err) {
return next(err);
} else {
newUser.sites.push(site); // push site'id in sites field in user
newUser.save(); // save user after site'id has been push
};
});
};
res.redirect('users/' + username);
});
...
and I get ReferenceError: res is not defined
Any help would be appreciated as I am starting Mean dev.
Thanks a lot

You shouldn't be handling redirects in here - the function of the strategy is to determine whether the user is authenticated or not.
Redirects can then be done in the middleware:
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login'
}));
http://passportjs.org/guide/authenticate/

Related

Passport JS successRedirect hangs in Node.js

I am using passports local-signup and can create a user via a form and have the page successfully redirect to a page I have specified.
My issue at the moment is that upon redirect the page just hangs. I see there are others out there who have experienced similar but looking at what I have I cannot work out why my example is hanging.
I carry out some simple validation of the form first and if that's ok I proceed with the passport config:
app.post('/signup', function(req, res, next) {
// Capture form details for when validation fails so can repopulate
var form = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email
}
var first_name = req.body.first_name;
var last_name = req.body.last_name;
var email = req.body.email;
var password = req.body.password;
var password_confirmation = req.body.password_confirmation;
// Validation
req.checkBody('first_name', 'First Name is required').notEmpty();
req.checkBody('last_name', 'Last Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password_confirmation', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if (errors) {
res.render('home', {
errors: errors,
form: form
});
}
else {
passport.authenticate('local-signup', {
successRedirect : '/members', // redirect to the secure profile section
failureRedirect : '/', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
})(req, res, next);
}
});
local-signup
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// asynchronous
// User.findOne won't fire unless data is sent back
process.nextTick(function(callback) {
// we are checking to see if the user trying to sign up already exists
// User.findOne declared in User Model
User.findOne(email, function(err, isNotAvailable, user) {
if (err) return done(err);
// check to see if theres already a user with that email
if (isNotAvailable == true) {
return done(null, false, { message: 'That email is already taken.' });
} else {
newUser = new Object();
newUser.email = email;
newUser.password = bcrypt.hashSync(password, 10);
pool.query('INSERT INTO users(email, password) VALUES($1, $2) RETURNING *', [newUser.email, newUser.password], function (err, result) {
if(err){
console.log(err);
return console.error('error running query', err);
}
newUser.id = result.rows[0].id;
return done(null, newUser);
});
} // isNotAvailable
}); //User.findOne
});
}));
try this way :
passport.authenticate('local', {
successRedirect : '/members',
failureRedirect : '/',
failureFlash : true
})(req, res, next);

On post route send email with nodemailer and save user to mongodb with passport.authenticate

I am trying to send a welcome email after a user signs up with nodemailer and also adding the user to mongodb with passport.authenticate on the same post route. I am able to get this to work separately i.e. either sending email or adding the user to the database but can't seem to get them to work together. I am new to nodejs and would really appreciate any help. Here is the route I am trying to get to work:
router.post('/signup', function(req, res,next) {
async.waterfall([
function(done) {
passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/signup',
failureFlash : true
});
},
function(user, done) {
var transporter = nodeMailer.createTransport({
service: 'SendGrid',
auth: {
user: 'user',
pass: 'password'
}
});
var mailOptions = {
to: user.email,
from: 'me#gmail.com',
subject: 'Welcome to the site',
html: '<p> This is html, did I render correctly?</p>'
};
transporter.sendMail(mailOptions, function(err){
done(err);
});
}
], function(err) {
res.redirect('/signup');
});
});
Here is the signup strategy with passport:
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport){
passport.use('signup', new LocalStrategy({
usernameField : 'email',
passReqToCallback : true
},
function(req, email, password, done) {
findOrCreateUser = function(){
// find a user in Mongo with provided username
User.findOne({ 'email' : email }, function(err, user) {
// In case of any error, return using the done method
if (err){
req.flash('error','Email Already Exists',err.message);
return done(err);
}
// already exists
if (user) {
console.log('User already exists with username:');
return done(null, false, req.flash('error','Email Already Exists'));
} else {
// if there is no user with that email
// create the user
var newUser = new User();
// set the user's local credentials
newUser.password = createHash(password);
newUser.email = req.param('email');
newUser.firstName = req.param('firstName');
newUser.lastName = req.param('lastName');
// save the user
newUser.save(function(err) {
if (err){
console.log('Error in Saving user: '+err);
return done(null, false, req.flash('error',err.message));
}
console.log('User Registration succesful');
return done(null, newUser);
});
}
});
};
// Delay the execution of findOrCreateUser and execute the method
// in the next tick of the event loop
process.nextTick(findOrCreateUser);
})
);
// Generates hash using bCrypt
var createHash = function(password){
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
}
}
Thanks in advance for the help!
Why don't you move the email sending logic to the passport signup strategy?

Basic passport.js signup function fails, thinks username has already been taken

I'm using passport.js to get a basic signup function established for a Node + Express + Sequelize app. Right now I have an empty database, and am using just the passport-local strategy to get the user's email and password from a form, check this against the database to ensure the email is not associated with another account, and then once this has been established, create the user.
Here are the relevant sections of my code:
./config/passport.js
const db = require('./sequelize');
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(user, done) {
db.User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(email, password, done){
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
db.User.findOne({ email : email }, function(err, user) {
// if there are any errors, return the error
if (err)
return done(null, false, {message: err});
// check to see if there's already a user with that email
else if (user) {
return done(null, false, {message: 'User already exists'});
}
else {
return done(null, true, {message: 'User created'});
}
});
});
}
));
module.exports = passport;
app.js
app.post('/signup', function(req, res, next){
const user = req.body;
passport.authenticate('local', function(err, user, info){
if (err){
res.send({success: false, message: 'authentication failed'});
}
if (!user) {
console.log(user);
res.send({message: "user already found"});
}
else{
db.User.create({
email: req.body.username,
password: req.body.password
});
console.log(info);
res.json({message: "user successfully signed up"});
}
})(req, res, next)
});
./config/sequelize
const path = require('path');
const Sequelize = require('sequelize');
const _ = require('lodash');
const config = require('./config');
const db = {};
// create your instance of sequelize
const sequelize = new Sequelize(config.db.name, config.db.username, config.db.password, {
host: config.db.host,
port: config.db.port,
dialect: 'mysql',
storage: config.db.storage
});
//Instantiate the database
sequelize
.authenticate()
.then(function(err) {
console.log('Connection has been established successfully.');
}, function (err) {
console.log('Unable to connect to the database:', err);
});
/* this is where all of the MODELS will be defined for the time being */
const User = sequelize.define('User', {
username: Sequelize.STRING,
email: Sequelize.STRING,
password: Sequelize.STRING
});
sequelize.sync();
db.User = User;
db.Sequelize = Sequelize;
db.sequelize = sequelize;
module.exports = db;
However, when I run the app with the clean database, !user in the app.js file evaluates to false, and I am unable to sign up new users because it would seem to be that the strategy thinks there is already an existing user with that email in the database. What do I need to do to remedy situation?
db.User.findOne({ where: { email : email }})
.then(
function(user) {
if (user) {
return done(null, false, {message: 'User already exists'});
} else {
return done(null, true, {message: 'User created'});
);
Try to change your code
using redirects here (app.js):
app.post('/signup', passport.authenticate('local', {
successRedirect : '/profile',
failureRedirect : '/signup',
failureFlash : true
}));
using promises for sequelize queries (./config/passport.js):
passport.deserializeUser(function(id, done) {
db.User.findById(id).then(function(user) {
done(err, user.dataValues);
})
.catch(function(err){
done(err, null);
});
});
passport.use('local', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done){
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
db.User.findOne({ where: {email : email }})
.then(function(user) {
if (user !== null) {
done(null, false, {message: 'User already exists'});
}
else {
db.User.create({
email: email,
password: password
})
.then(function(user){
done(null, user);
})
.catch(function(err){
console.log(err);
done(null, false);
});
}
})
.catch(function(err){
// if there are any errors, return the error
return done(null, false, {message: err});
});
});
}
));

how can i unit test passportjs with mocha?

i would like to test this method using mocha and i don't know where to start ?
the route :
app.post('/signup', passport.authenticate('local-signup', {
failureRedirect: '/#/',
failureFlash: true
}),
function(req, res) {
res.jsonp(req.user);
});
and here is the definition of my service :
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
pseudoField: 'pseudo',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, pseudo, done) {
// asynchronous
// User.findOne wont fire unless data is sent back
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({
'local.email': email
}, function(err, user) {
// if there are any errors, return the error
if (err)
return done(err);
// check to see if theres already a user with that email
if (user) {
console.log('That email is already taken');
//var newUser = new User();
return done(404, null);
// return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else {
// if there is no user with that email
// create the user
console.log('creation new user');
var newUser = new User();
// set the user's local credentials
newUser.local.email = email;
newUser.local.password = newUser.generateHash(password);
newUser.local.pseudo = pseudo;
console.log(pseudo);
console.log(newUser.local);
// save the user
console.log('going to save in bdd');
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
}));
i just need some help to know how i could test this methode and how to call it.

Passport authorization callback redirects to beginning (Box)

I'm attempting to authenticate a user using Box.com OAuth2.0. I make the initial call and login which redirects to my callback url with the authorization code. At this point my server handles the callback using passport but for some reason it returns a 302 and redirects to the beginning of the oauth authentication process.
//box authentication routes
app.get('/api/box', passport.authorize('box'));
// the callback after box has authorized the user
app.get('/api/box/callback', passport.authorize('box', {
successRedirect: '/',
failureRedirect: '/login'
})
);
I verified that my route is being called by using my own handler and the request data seems to be correct. Box returns a 200 and the url contains the authorization code.
app.get('/api/box/callback', function(req, res) {
console.log('auth called')
});
This is my passport strategy:
passport.use(new BoxStrategy({
clientID: config.box.clientID,
clientSecret: config.box.clientSecret,
callbackURL: config.box.callbackURL,
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
process.nextTick(function() {
if(!req.user) {
// try to find the user based on their google id
User.findOne({ 'box.id' : profile.id }, function(err, user) {
if (err)
return done(err);
if (user) {
// if a user is found, log them in
return done(null, user);
} else {
// if the user isnt in our database, create a new user
var newUser = new User();
// set all of the relevant information
newUser.box.id = profile.id;
newUser.box.accessToken = accessToken;
newUser.box.refreshToken = refreshToken;
newUser.box.name = profile.name;
newUser.box.email = profile.login;
// save the user
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
} else {
// user already exists and is logged in, we have to link accounts
var user = req.user;
// update the current users box credentials
user.box.id = profile.id;
user.box.accessToken = accessToken;
user.box.refreshToken = refreshToken;
user.box.name = profile.name;
user.box.email = profile.login;
// save the user
user.save(function(err) {
if (err)
throw err;
return done(null, user);
});
}
});
}
));
Would appreciate any insight as to what might be causing this redirect behavior.
It ended up being an instance of PeerServer that was somehow causing the redirect.

Categories