Как с помощью PassportJS передать дополнительные поля формы в стратегию локальной аутентификации?

99

Я использую passportJS и я хотел поставить больше , чем просто req.body.usernameи req.body.passwordк моей стратегии аутентификации (паспорт-местный).

У меня есть 3 поля формы: username, password, &foo

Как мне получить доступ req.body.fooиз моей локальной стратегии, которая выглядит так:

passport.use(new LocalStrategy(
  {usernameField: 'email'},
    function(email, password, done) {
      User.findOne({ email: email }, function(err, user) {
        if (err) { return done(err); }
        if (!user) {
          return done(null, false, { message: 'Unknown user' });
        }
        if (password != 1212) {
          return done(null, false, { message: 'Invalid password' });
        }
        console.log('I just wanna see foo! ' + req.body.foo); // this fails!
        return done(null, user, aToken);

      });
    }
));

Я вызываю это внутри своего маршрута (не как промежуточное ПО маршрута) вот так:

  app.post('/api/auth', function(req, res, next) {
    passport.authenticate('local', {session:false}, function(err, user, token_record) {
      if (err) { return next(err) }
      res.json({access_token:token_record.access_token});
   })(req, res, next);

  });
k00k
источник

Ответы:

183

Есть passReqToCallbackопция, которую вы можете включить, например:

passport.use(new LocalStrategy(
  {usernameField: 'email', passReqToCallback: true},
  function(req, email, password, done) {
    // now you can check req.body.foo
  }
));

Когда, set reqстановится первым аргументом обратного вызова verify, и вы можете проверять его по своему усмотрению.

Джаред Хэнсон
источник
8
Отлично работает, спасибо. Есть passReqToCallbackв руководстве? Я этого не видел.
k00k 02
2
Еще нет. Я отстаю от добавления новых функций / параметров в руководство.
Джаред Хэнсон
Спасибо, избавил меня от многих проблем
binarygiant 09
9
Это действительно полезно для реализации мультитенантной / мультитенантной аутентификации, но в моих поисках в Google не нашлось. Надеюсь, мой комментарий поможет людям найти этот ответ в будущем.
Крис Даль
Это очень полезно. Но можно ли установить usernameFieldпо условию? У меня есть два варианта: один - электронная почта, а другой - номер телефона. и таблица входа в систему содержит эти два поля вместе с паролем.
Мэтью Джон
1

В большинстве случаев нам нужно предоставить 2 варианта входа в систему

  • по электронной почте
  • с мобильного

Это просто, мы можем взять общее имя пользователя и запросить $ или двумя вариантами, я опубликовал следующие фрагменты, если у кого-то есть такой же вопрос.

Мы также можем использовать passReqToCallback - лучший вариант, спасибо @Jared Hanson

passport.use(new LocalStrategy({
    usernameField: 'username', passReqToCallback: true
}, async (req, username, password, done) => {
    try {
        //find user with email or mobile
        const user = await Users.findOne({ $or: [{ email: username }, { mobile: username }] });

        //if not handle it
        if (!user) {
            return done(null, {
                status: false,
                message: "That e-mail address or mobile doesn't have an associated user account. Are you sure you've registered?"
            });
        }

        //match password
        const isMatch = await user.isValidPassword(password);
        debugger
        if (!isMatch) {
            return done(null, {
                status: false,
                message: "Invalid username and password."
            })
        }

        //otherwise return user
        done(null, {
            status: true,
            data: user
        });
    } catch (error) {
        done(error, {
            status: false,
            message: error
        });
    }
}));
Бхагват Ланде
источник