nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.46k stars 279 forks source link

How to use multiple strategies in passportjs #4164

Closed MitulKheni-solution closed 1 year ago

MitulKheni-solution commented 1 year ago

Details

How can I combine multiple strategies in one passport.authenticate function?

Node.js version

Not applicable.

Example code

I have 2 social authentication strategies in my Node.js app. One is Google-OAuth and another one is GitHub. There will be more strategies as well (Azure-ad and email-password).

Currently, I am using it like following:

router
    .route('/hello')
    .get(
        passport.authenticate('google', { successRedirect: '/v1/any', failureRedirect: '/login', scope: ['email', 'profile'] }),
        (req: Request, res: Response, next: NextFunction) => {
            try {
                return res.locals.success('Hello World');
            } catch (error) {
                next(error);
            }
        }
    );

below is the GitHub strategy:

router
    .route('/hello1')
    .get(
        passport.authenticate('github', { successRedirect: '/v1/any', failureRedirect: '/login', scope: ['user:email'] }),
        (req, res, next) => {
            try {
                return res.locals.success('Hello World');
            } catch (error) {
                next(error);
            }
        }
    );

(of course, this is not in production)

I have read a solution where I can pass the array of strategies in the passport.authenticate method's first argument, But that will not work as scopes are different for Google and GitHub

Or I can use it only like this?

router.route('/hello').get(
  (req: Request, res: Response, next: NextFunction) => {
    const strategies = [
      { name: 'google', scope: ['email', 'profile'] },
      { name: 'github', scope: ['user:email'] },
    ];

    const { strategy } = req.query;
    const strategyConfig = strategies.find((s) => s.name === strategy);

    if (strategyConfig) {
      passport.authenticate(strategyConfig.name, {
        scope: strategyConfig.scope,
      })(req, res, next);
    } else {
      return res.status(400).json({ error: 'Invalid authentication strategy' });
    }
  },
  (req: Request, res: Response, next: NextFunction) => {
    try {
      return res.locals.success('Hello World');
    } catch (error) {
      next(error);
    }
  }
);

Operating system

Linux - Ubuntu

Scope

authentication, code

Module and version

passport

bmuenzenmeyer commented 1 year ago

this question would be better answered in the passport community.

I found all of these potential leads with a quick search for multiple strategies

Additionally, the closed issues for the same question seem to indicate this might not be possible. I suggest you do further research there.