fitims fitims - 1 year ago 58
Node.js Question

How do I persist form data on redirect if Passport authentication fails?

I am trying to use passport to authenticate users on the web page. Everything works fine, except when authentication fails and the passport redirects the user to the same rout, all the data on the form is lost. Is there a way to persist the data and pass them back to the form.

I have the following in routes.js

// =====================================
// SIGNUP ==============================
// =====================================
// show the signup form
app.get('/signup', function(req, res) {
// render the page and pass in any flash data if it exists
signup.isAuthenticated = req.isAuthenticated();
signup.user = req.user;
signup.message = req.flash('signupMessage');
res.render('signup', signup);

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

on my passport.js I have the following:

// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'

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
// this function is used when signing up
function(req, email, password, done) {
// TODO: get the user from data
if(email == '') {
// user email already exists
console.log('user already exists !');
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
else {

// if there is no user with that email
// create the user
var newUser = { username : '', name : 'Name Surname' }; = email;
newUser.local.password = newUser.generateHash(password);
return done(null, newUser);

and my server.js has the following:

// server.js

// set up ======================================================================
// get all the tools we need
var express = require('express');
var path = require('path');
var app = express();
var port = process.env.PORT || 3000;
// var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var multer = require('multer');

var configDB = require('./config/database.js');

// configuration ===============================================================
// mongoose.connect(configDB.url); // connect to our database

require('./config/passport')(passport); // pass passport for configuration

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({ extended: false }));

// use multer to process multi-part requests and multer to save our files by default to /uploads/ directory
dest : path.join(__dirname, '/uploads/'),
limits : {
fieldNameSize : 200, // 200 bytes
files : 5, // 5 files
fileSize : 5194304000000, // 5 GB
fields : 50 // 50 fields on the form

app.use(cookieParser()); // read cookies (needed for auth)
app.use(express.static(path.join(__dirname, 'public')));

// required for passport
secret: 'mylongsecretpassphrase',
resave : true,
saveUninitialized : true
})); // session secret

app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session

// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport

// show error page if the resource is not found
app.use('*', function(req, res) {
res.render('page-error', {
title : 'myWeb - Page Error',
description : 'my web page',
keywords : 'keywords1, keywords2, keywords3'

// launch ======================================================================
console.log('Node listens on port ' + port);

any help would be greatly appreciated !

Answer Source

If you don't want to lose form data, you could use AJAX to send your form, and send a status 401 Unauthorized in case the auth fails. Passport sends the 401 by default so the following should work (untested, may contain typos) :'/login', function(req, res, next) {
      function(req, res) {
       // If this function gets called, authentication was successful. If not, your ajax call gets a 401 status and you can handle it in .fail()

A bit of explanation from the passport website :

By default, if authentication fails, Passport will respond with a 401 Unauthorized status, and any additional route handlers will not be invoked. If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.