web-dev-qa-db-fra.com

Utilisez plusieurs stratégies locales dans PassportJS

J'essaie d'utiliser plusieurs stratégies LOCALES avec PassportJS. Je n'essaie pas d'utiliser local, facebook et gmail, etc. J'ai deux ensembles d'utilisateurs stockés dans des objets séparés et je veux utiliser une stratégie locale pour authentifier les deux. En l'état, je ne peux pas utiliser la même stratégie locale pour les deux car ils ont des propriétés d'objet différentes, ce qui m'interroge sur différents objets. Y a-t-il un moyen de faire ça? OR toute suggestion à ce sujet serait grandement appréciée.

35
Plattaz

Je ne pense pas que ce soit possible, car pour autant que je sache, vous avez besoin d'une méthode pour `` transmettre '' une demande à la deuxième stratégie lorsque la première échoue, et je ne pense pas que ce soit possible.

Mais vous pouvez peut-être utiliser une stratégie locale et simplement essayer d'authentifier les données entrantes à l'aide des deux méthodes.

Comme exemple simple (en utilisant Mongoose comme exemple de base de données):

passport.use(new LocalStrategy(function(username, password, done) {
  Model1.findOne({ username : username }, function(err, user) {
    // first method succeeded?
    if (!err && user && passwordMatches(...)) {
      return done(null, user);
    }
    // no, try second method:
    Model2.findOne({ name : username }, function(err, user) {
      // second method succeeded?
      if (! err && user && passwordMatches(...)) {
        return done(null, user);
      }
      // fail! 
      done(new Error('invalid user or password'));
    });
  }); 
}));

Pour la sérialisation/désérialisation, vous devrez peut-être stocker une propriété dans l'objet user que vous transmettez à done pour indiquer le modèle requis pour désérialiser l'utilisateur.

5
robertklep

Vous pouvez nom vos stratégies locales pour les séparer.

// use two LocalStrategies, registered under user and sponsor names

      // add other strategies for more authentication flexibility
  passport.use('user-local', new LocalStrategy({
      usernameField: 'email',
      passwordField: 'password' // this is the virtual field on the model
    },
    function(email, password, done) {
      User.findOne({
        email: email
      }, function(err, user) {
        if (err) return done(err);

        if (!user) {
          return done(null, false, {
            message: 'This email is not registered.'
          });
        }
        if (!user.authenticate(password)) {
          return done(null, false, {
            message: 'This password is not correct.'
          });
        }
        return done(null, user);
      });
    }
  ));

    // add other strategies for more authentication flexibility
    passport.use('sponsor-local', new LocalStrategy({
            usernameField: 'username',
            passwordField: 'password' // this is the virtual field on the model
        },
        function(username, password, done) {
            Sponsor.findOne({
                'primaryContact.username': username
            }, function(err, sponsor) {
                if (err) return done(err);

                if (!sponsor) {
                    return done(null, false, {
                        message: 'This email/username is not registered.'
                    });
                }
                if (!sponsor.authenticate(password)) {
                    return done(null, false, {
                        message: 'This password is not correct.'
                    });
                }
                return done(null, sponsor);
            });
        }
    ));

Les codes de contrôleur ultérieurs s'y réfèrent par leur nom.

/**
 * User Login
 */
exports.loginUser = function (req, res, next) {
    passport.authenticate('user-local', function(err, user, info) {
        var error = err || info;
        if (error) return res.json(401, error);

        req.logIn(user, function(err) {

            if (err) return res.send(err);
            res.json(req.user.userInfo);
        });
    })(req, res, next);
};

/**
 * Sponsor Login
 */
exports.loginSponsor = function (req, res, next) {
    passport.authenticate('sponsor-local', function(err, sponsor, info) {
        var error = err || info;
        if (error) return res.json(401, error);

        req.logIn(sponsor, function(err) {
            if (err) return res.send(err);
            res.json(req.sponsor.profile);
        });
    })(req, res, next);
};

Plus tard, quand viendra le moment de sérialiser votre utilisateur, vous voudrez peut-être faire quelque chose comme ça.

// serialize
passport.serializeUser(function(user, done) {            
  if (isUser(user)) {
    // serialize user
  } else if (isSponsor(user)) {
    // serialize company
  }
});
154
Matthew Payne

vous pouvez utiliser quelque chose comme ça pour plusieurs stratégies locales

passport.use('local.one', myLocalStrategy1);
passport.use('local.two', myLocalStrategy2);
passport.use('local.three', myLocalStrategy3);

...

app.get('/login/s1', passport.authenticate('local.one');
app.get('/login/s2', passport.authenticate('local.two');
app.get('/login/s3', passport.authenticate('local.three');
2
RANJEET