Passport Authenticate doesn't redirect

2019-03-06 12:47发布

问题:

I was writing a local-signup strategy and noticed that it doesn't work so I stepped back and tried to authenticate against my empty collection. Every time I submit the form it takes ~30-40s until it results in a timeout. I ensured passport.authenticate() is called but it seems ike it's not doing any redirects and hence it is timing out because I am not rendering something either.

Questions:

  1. I expected that it would do a redirect to the failureUrl (which is '/signup'), but instead nothing is happening. What am I doing wrong here?
  2. Why there is no single log message coming from passport? This is driving me crazy because I have absolutely no idea what is going wrong there.
  3. I am new to node.js and as far as I got I don't need to pass the configured passport object to the router but instead I can just do const passport = require('passport') is that correct?

This is my function handler for the /signup route:

function processSignup (req, res) {
    logger.info("POST request received")
    logger.info(req.body)
    passport.authenticate('local', {
        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
    })
}

Winston prints:

7:32:04 PM - info: POST request received 7:32:04 PM - info: username=dassd@dass.de, password=dasdsa, submit=Register

My passport.js file looks like this:

const LocalStrategy = require('passport-local').Strategy
const User = require('./user-model')
const passport = require('passport')

// expose this function to our app using module.exports
function config() {
    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(new LocalStrategy(
        function(username, password, done) {
            User.findOne({ username: username }, function(err, user) {
                if (err) { return done(err); }
                if (!user) {
                    return done(null, false, { message: 'Incorrect username.' });
                }
                if (!user.validPassword(password)) {
                    return done(null, false, { message: 'Incorrect password.' });
                }
                return done(null, user);
            });
        }
    ));
}

module.exports = {
    config: config
}

The relevant snipped of my app.js:

// required for passport
require('./authentication/passport').config();
app.use(cookieParser())
app.use(bodyParser())
app.use(session({ 
    secret: 'secretToBeChanged',
    saveUninitialized: false,
    resave: false
}))
app.use(passport.initialize())
app.use(passport.session()) // persistent login sessions
app.use(flash()) // use connect-flash for flash messages stored in session

回答1:

After a quick look at the documentation for passportjs, I think you need to do something like this:

function processSignup (req, res, next) {
    logger.info("POST request received")
    logger.info(req.body)
    const handler = passport.authenticate('local', {
        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
    });
    handler(req, res, next);
}

passport.authenticate() returns a function that is meant to be used as the route handler function.
Normally, you would type something like:

app.post('/login', passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/login',
  failureFlash: true 
}));

But since you have abstracted with your own route handler function, you need to invoke the one returned from passport.authenticate().



回答2:

In the end Mikael Lennholm was right and he pointed me into the right direction. I couldn't find that in any passport.js tutorials. However the passport.js documentation contains this code snippet which represents the same but I prefer it's code style:

passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err); }
    if (!user) { return res.redirect('/login'); }
    req.logIn(user, function(err) {
      if (err) { return next(err); }
      return res.redirect('/users/' + user.username);
    });
  })(req, res, next);