64

Using Passport.js is there a way for me to specify multiple authentication providers for the same route?

For example (from passport's guide) can I use local and facebook and twitter strategies on the sample route below?

app.post('/login',
  passport.authenticate('local'), /* how can I add other strategies here? */
  function(req, res) {
    // If this function gets called, authentication was successful.
    // `req.user` contains the authenticated user.
    res.redirect('/users/' + req.user.username);
  });
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
cgiacomi
  • 4,629
  • 6
  • 27
  • 33

1 Answers1

121

Passport's middleware is built in a way that allows you to use multiple strategies in one passport.authenticate(...) call.

However, it is defined with an OR order. This is, it will only fail if none of the strategies returned success.

This is how you would use it:

app.post('/login',
  passport.authenticate(['local', 'basic', 'passport-google-oauth']), /* this is how */
     function(req, res) {
       // If this function gets called, authentication was successful.
       // `req.user` contains the authenticated user.
       res.redirect('/users/' + req.user.username);
});

In other words, the way to use it, is passing an array containing the name of the strategies you want the user to authenticate with.

Also, dont forget to previously set up the strategies you want to implement.

You can confirm this info in the following github files:

Authenticate using either basic or digest in multi-auth example.

Passport's authenticate.js definition

Mrchief
  • 75,126
  • 20
  • 142
  • 189
Danilo Ramirez
  • 1,598
  • 1
  • 16
  • 22
  • 1
    How can I tell which authentication strategy eventually used to authenticate the users? I can of course a different endpoint for each strategy, but I am trying to avoid it. – asaf am Jan 07 '15 at 16:14
  • @asafam as far as I remember, the req.user holds the info used by the login strategy. Would have to check it out tho.... Most of the info used in the session (after) is kept in the req object – Danilo Ramirez Jan 20 '15 at 19:42
  • Thanks @DaniloRamirez. I am using a sessionless approach for my API server. I found the answer to be with the req.info object that can be set with custom data. – asaf am Jan 21 '15 at 21:11
  • 4
    I cannot figure out how this is useful. Basic Strategy needs to be done every request, at least to work with something like curl. While Local Strategy will keep sessions for a browser. So if I want to have an API that is sessioned for the browser via a login, but BasicAuth with credentials for each request via curl, I don't seem to be able to do it. Is that possible? – jeremykentbgross Feb 22 '15 at 14:31
  • 1
    One thing I'm still missing is how serialize/deserialize is supposed to work, since it's the same for all the strategies. Are we supposed to guarantee that all the strategies are returning the same userModel? – shabunc Dec 03 '16 at 01:27
  • Same here. I have two user models for my application: user and device. Devices use a token strategy, while users use local. What's the best practice here? – Jim B. Oct 04 '17 at 02:12
  • @JimBaldwin I guess you can setup different endpoints and specify the logic to select from the two user models via req.users. Maybe userType that would point to user or device models – Danilo Ramirez Dec 06 '17 at 01:05
  • Sorry, I know this is old, but I want the user to decide which strategy they want to use. How does that work out? – ndtreviv Aug 16 '19 at 10:33
  • @DaniloRamirez Is there a way also to pass an array of settings for each of the strategies passed? – bertonc96 Dec 10 '19 at 09:46