Jak przy użyciu PassportJS przekazać dodatkowe pola formularza do lokalnej strategii uwierzytelniania?

98

Używam passportJS a ja chcąc dostarczyć więcej niż tylko req.body.usernamei req.body.passworddo mojej strategii uwierzytelniania (paszport-miejscowy).

Mam 3 pól formularza: username, password, ifoo

Jak uzyskać dostęp req.body.fooz mojej strategii lokalnej, która wygląda następująco:

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);

      });
    }
));

Nazywam to wewnątrz mojej trasy (nie jako oprogramowanie pośredniczące tras) w następujący sposób:

  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
źródło

Odpowiedzi:

181

Istnieje passReqToCallbackopcja, którą możesz włączyć, na przykład:

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

Kiedy, set reqstaje się pierwszym argumentem w wywołaniu zwrotnym weryfikacji i możesz go sprawdzić, jak chcesz.

Jared Hanson
źródło
8
To działa świetnie, dzięki. Jest passReqToCallbackw przewodniku? Nie widziałem tego.
k00k
2
Jeszcze nie. Spóźniłem się z dodawaniem nowych funkcji / opcji do przewodnika.
Jared Hanson
Dzięki, zaoszczędziłem wiele kłopotów
binarygiant
9
Jest to bardzo pomocne przy implementacji uwierzytelniania wielu dzierżawców / dzierżawców, ale nie pojawiło się w moich wyszukiwaniach Google. Mam nadzieję, że mój komentarz pomoże ludziom znaleźć tę odpowiedź w przyszłości.
Kris Dahl
To jest bardzo pomocne. Ale czy można ustawić usernameFieldzgodnie z warunkiem? Mam dwie opcje: jedna to e-mail, a druga to numer telefonu. a tablica logowania zawiera te dwa pola wraz z hasłem.
Mathew John
1

W większości przypadków musimy zapewnić 2 opcje logowania

  • z e-mailem
  • z telefonem komórkowym

To proste, możemy wziąć wspólną nazwę użytkownika z pola i zapytać $ lub za pomocą dwóch opcji, opublikowałem następujące fragmenty, jeśli ktoś ma to samo pytanie.

Możemy również użyć „passReqToCallback” jako najlepszej opcji, dzięki @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
        });
    }
}));
Bhagvat Lande
źródło