Using PassportJS, how does one pass additional form fields to the local authentication strategy?
Asked Answered
T

2

108

I'm using passportJS and I'm wanting to supply more than just req.body.username and req.body.password to my authentication strategy (passport-local).

I have 3 form fields: username, password, & foo

How do I go about accessing req.body.foo from my local strategy which looks like:

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

      });
    }
));

I'm calling this inside my route (not as route middleware) like so:

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

  });
Treytri answered 2/8, 2012 at 19:12 Comment(0)
M
197

There's a passReqToCallback option that you can enable, like so:

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

When, set req becomes the first argument to the verify callback, and you can inspect it as you wish.

Massasauga answered 2/8, 2012 at 19:49 Comment(6)
That works great, thanks. Is passReqToCallback in the guide? I didn't see it.Treytri
Not yet. I'm behind on adding new features/options to the guide.Massasauga
This is really helpful for implementing multi-tenant / multi-tenancy authentication, but didn't come up in my google searches. Hopefully my comment will help folks find this answer in the future.Roye
This is very helpful. But is it possible to set the usernameField according to a condition? I have two options: one is email and the other is phonenumber. and the login table contains these two field along with password.Vandervelde
Very useful. For anyone wondering, passReqToCallback also exists in the passport-http module. Based on this, I'd guess it's in many other strategies too.Comer
Did same but still getting missing credentials error @MathewJohnZales
B
1

In most common cases we need to provide 2 options for login

  • with email
  • with mobile

Its simple , we can take common filed username and query $or by two options , i posted following snippets,if some one have have same question .

We can also use 'passReqToCallback' is best option too , thanks @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
        });
    }
}));
Busch answered 14/6, 2019 at 10:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.