passport icon indicating copy to clipboard operation
passport copied to clipboard

passport.authorize() clearing req.user with multiple strategies

Open Leigham opened this issue 3 years ago • 5 comments

I have been trying to wrap my head around this issue for a while. from what I have been reading passport.authorize() shouldn't clear current session. Strategies

 exports.SteamStrategy = new SteamStrategy(config.steam, (req, identifier, profile, done) => {
 
   return done(null, profile);
 });
 exports.OAuth2Strategy = new OAuth2Strategy(config.oauth2, (req, accessToken, refreshToken, params, profile, done) => {
 console.log(req.user); // undefined (when authenticated with steam)
   return done(null, profile);
 });

Routes

// -- steam auth routes
router.get('/steam', passport.authenticate('steam', { failureRedirect: '/' }), (req, res) => {
  res.redirect('/');
});
router.get('/steam/return', fixurl, passport.authenticate('steam', { failureRedirect: '/' }), (req, res) => {
  res.redirect('/')
});

// wordpress auth routes
router.get('/wordpress',passport.authorize('oauth2'), (req, res) => {
  res.redirect('/');
});
router.get('/wordpress/callback',passport.authenticate('oauth2', { failureRedirect: '/' }), (req, res) => {
  res.redirect('/');
});

req.user returns the right data on the steam strategy, but returns undefined on the oauth2 strategy,

https://github.com/jaredhanson/passport/issues/81

this is where I got the information to user authorize not authenticate. any confirmation if this is an issue. or just me being dumb.

Leigham avatar May 04 '21 09:05 Leigham

I can confirm. I have the same issue with Passport-twitter


Edit For anyone facing the same issue, I have solved it by attaching request params to the request's session. (hacky)

router.get('/connect/twitter', (req, res, next) => {
    const { localUrl } = req.query;
    Object.assign(req.session, {"calledFromUrl": localUrl})
    const authenticator = passport.authorize("twitter");
    authenticator(req, res, next);
});
router.get('/connect/twitter/callback/', (req, res, next) => {
        const localUrl = typeof (req.session as any).calledFromUrl === "string" ? (req.session as any).calledFromUrl : undefined;
        passport.authorize('twitter', (reqest, response) => {
            try {
                if (localUrl && typeof localUrl === 'string') {
                    return res.redirect(localUrl)
                }
            } catch {
                // just redirect normally below
            }
            res.redirect('/')
        })(req, res, next);
    }
);

AlanJereb avatar May 16 '21 21:05 AlanJereb

Also looking for a solution for this - connecting multiple services is essential for a lot of sites and not being able to do this with Passport is a big bummer.

EDIT: Fixed my issue by setting express-session's cookie's property sameSite to 'lax'.

...
  app.use(
    expressSession({
      cookie: {
        sameSite: 'lax',
        httpOnly: true,
        maxAge: 7 * 24 * 60 * 60 * 1000
      },
...

Aimsucks avatar Sep 03 '21 16:09 Aimsucks

I can confirm the issue when using any OAuth2 strategy with .authorize() it does not matter if you use Facebook, Twitter or OAuth2 for any other service I tried, in the callback of the strategy - req.user is always empty.

ynfinite avatar May 19 '22 15:05 ynfinite

I ran into the same problem, it's a bit of a hacky solution but I got around it by using req.session?.passport?.user and deserializing the user manually instead of using req.user in the callback.

nathan6am avatar Jun 04 '22 00:06 nathan6am

I can confirm the issue when using any OAuth2 strategy with .authorize() it does not matter if you use Facebook, Twitter or OAuth2 for any other service I tried, in the callback of the strategy - req.user is always empty.

Pls how did you solve this?

Tosinkoa avatar Oct 18 '22 09:10 Tosinkoa