5
votes

Folloing the sample https://scotch.io/tutorials/easy-node-authentication-setup-and-local I have create a simply signup app to test passport.

I'm using Express 4 and connect-flash module.

My routes are as follow, that is on GET /signup I show the signup form with any possible signupMessage flash message (always undefined). On POST /signup I try to authenticate credentials:

router.get('/signup', function(req, res) {
  debug('GET signup flash message "%s"',req.flash('signupMessage'));
  res.render('signup',  { message: req.flash('signupMessage') });
});

// process the signup form
router.post('/signup', passport.authenticate('local-signup', {
  successRedirect : '/profile', // redirect to the secure profile section
  failureRedirect : '/signup', // redirect back to the signup page if there is an error
  failureFlash : true // allow flash messages
}));

My passport related code is place next. It works but the lines like return done(null, false, req.flash('signupMessage', 'That email is already taken.')); seems that must set the request flash message seems not work because the flash message is never shown in the signup form shown by the GET method.

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) {

    debug("Auth");

    // asynchronous
    // User.findOne wont fire unless data is sent back
    process.nextTick(function() {

    debug("before findOne");

      // 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) {

        debug("inside findOne");

          // 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) {
            debug('user exists');
            return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
          } else {

            debug('creating new user');

            // if there is no user with that email
            // create the user
            var newUser            = new User();

            // set the user's local credentials
            newUser.local.email    = email;
            newUser.local.password = newUser.generateHash(password);

            // save the user
            newUser.save(function(err) {
              if (err) {
                throw err;
              }
              return done(null, newUser);
            });
          }

      });    

    });

}));

After looking for help I also try to put:

return done(null, false, {message: 'That email is already taken.'});

and in the GET /signup method use:

router.get('/signup', function(req, res) {
  res.render('signup',  { message: req.flash('error') });
});

but that doesn't works.

Anybody can help me?

Thanks.

2
It seems like you've answered your own problem, which is great! Rather than editing your question, it's usually preferred if you post the solution as an answer, so that other people that have the same problem will be able to find it more easily in the future. - ttarik

2 Answers

6
votes

For anyone that can have a similar problem I found my error was in sessions configuration.

As docs indicates, if you set secure cookie option, your connection must be over HTTPS or cookie will not be created. That was the reason neither normal and flash messages doesn't work.

2
votes
var session = require('express-session');
var flash = require('express-flash');
var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(session({
    secret: config.sessionKey,
    resave: true,
    saveUninitialized: true,
}));
app.use(flash());