web-dev-qa-db-fra.com

Nodejs et PassportJs: redirige le middleware après passport.authenticate non appelé en cas d'échec

Je n'ai pas de page de connexion mais j'ai plutôt un formulaire de connexion qui apparaît sur chaque page. Je souhaite rediriger les utilisateurs vers la même page sur laquelle ils se trouvaient, que l'authentification ait réussi ou non (avec les messages flash appropriés)

Prenez le code suivant:

app.post('/login', validateLogin, passport.authenticate('local-login'), function(req, res) {

    var redirectUrl = '/'; 

    if(req.body.to.length > 0){
        redirectUrl = req.body.to;  
    }

    console.log("THIS IS ONLY CALLED IF passport.authenticate() IS SUCCESSFUL");
    res.redirect(redirectUrl);
});

Je ne vois le middleware final ci-dessus appelé que si l'authentification est réussie. Si cela échoue, alors passeport semble me rediriger vers/login sous la forme d'une demande d'obtention. Dans mon application, cette page n'existe pas.

Si je passe un objet options supplémentaire en tant que paramètre dans la fonction d’authentification du passeport, cela fonctionne:

app.post('/login', validateLogin, passport.authenticate('local-login', {

successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/signup', // redirect back to the signup page. THIS IS JUST FOR TESTING TO SEE IF THE REDIRECT ON FAIL WORKS.
    failureFlash : true, // allow flash messages

}


));

Mais ce faisant, je perds la possibilité de choisir où rediriger l'utilisateur. Il semble que le passeport prenne le contrôle sur l'endroit où l'utilisateur est redirigé en cas d'échec de l'authentification. Comment puis-je réparer cela? Ou est-ce un bug? L'authentification du passeport doit-elle être le dernier middleware de la chaîne si l'authentification échoue?

Ceci est mon appel de fonction de stratégie locale:

//LOCAL LOGIN

passport.use('local-login', 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) { // callback with email and password from our form


    console.log("IN PASSPORT");

   if(email.length == 0 || password.length == 0){

       console.log("FIELDS ARE EMPTY"); 
      return done(null, false, req.flash('loginMessage', 'Fill in all values.'));

   }

    // 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 before anything else



        if (err){
            return done(err);
        console.log("db err");
        }
        // if no user is found, return the message
        if (!user){
            console.log("not user");
            return done(null, false, req.flash('loginMessage', 'Incorrect details.')); // req.flash is the way to set flashdata using connect-flash
        }    
        // if the user is found but the password is wrong

        if (!user.validPassword(password)){
            console.log("invalid pw");
            return done(null, false, req.flash('loginMessage', 'Incorrect details.')); // create the loginMessage and save it to session as flashdata
        }    
        // all is well, return successful user
        console.log("All OK");
        return done(null, user);
    });

}));
13
Paulie

Vous pouvez utiliser un rappel d'authentification personnalisé, comme décrit dans le dernier paragraphe, http://passportjs.org/guide/authenticate/ .

app.post('/login', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err); }
    // Redirect if it fails
    if (!user) { return res.redirect('/login'); }
    req.logIn(user, function(err) {
      if (err) { return next(err); }
      // Redirect if it succeeds
      return res.redirect('/users/' + user.username);
    });
  })(req, res, next);
});
30
ploutch

Je courais dans le même problème où les appels de redirection, qui suivent avec succès Auth Facebook

  • passport.authenticate ('facebook', ..)} _ 

.. n'étaient pas honorés.

Basé sur la stratégie 'locale' de passportJS - et un rappel gentil de celui de la réponse de @ ploutch ici ..

req.logIn(user, function(err) {
 ...
}

Pour Facebook, la configuration de cette route a fonctionné pour moi:

app.get(
        '/auth/facebook/callback',

        passport.authenticate
        (
            'facebook', 
            { failureRedirect: '/fbFailed' }
        ),

        function(req, res) 
        {
            var user = myGetUserFunc(); // Get user object from DB or etc

            req.logIn(user, function(err) {

              if (err) { 
                req.flash('error', 'SOMETHING BAD HAPPEND');
                return res.redirect('/login');
              }

              req.session.user = user;

              // Redirect if it succeeds
              req.flash('success', 'Fb Auth successful');
              return res.redirect('/user/home');
            });      
        }
); 
3
Gene Bo

Réponse complète, y compris:

  • Middleware pour définir redirectUrl
  • Messages flash
  • Ne pas renvoyer de valeurs qui ne seront pas utilisées

Créez simplement une valeur redirectTo dans votre middleware loginRequired:

var loginRequired = function(req, res, next) {
    if ( req.isAuthenticated() ) {
        next();
        return
    }
    // Redirect here if logged in successfully
    req.session.redirectTo = req.path;
    res.redirect('/login')
}

Et ensuite dans votre login POST:

router.post('/login', function(req, res, next) {
    passport.authenticate('local', function(err, user, info) {
        if ( err ) {
            next(err);
            return
        }
        // User does not exist
        if ( ! user ) {
            req.flash('error', 'Invalid email or password');
            res.redirect('/login');
            return
        }
        req.logIn(user, function(err) {
            // Invalid password
            if ( err ) {
                req.flash('error', 'Invalid email or password');
                next(err);
                return
            }
            res.redirect(req.session.redirectTo || '/orders');
            return
        });
    })(req, res, next);
});
0
mikemaccana