Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Losing Cookies/Session after redirect #51

Open
salman486 opened this issue Apr 22, 2024 · 4 comments
Open

Losing Cookies/Session after redirect #51

salman486 opened this issue Apr 22, 2024 · 4 comments

Comments

@salman486
Copy link

When apple redirects back with post request, I lose the current user session due sameSite Lax because it does not include cookie in callback with cross site post request.

@unitydevadtest
Copy link

The same. How to keep session like with other passports (google, facebook) with keepsessioninfo?

@lsjurczak
Copy link

@ananay is that doable to fix it?

@salman486
Copy link
Author

salman486 commented May 14, 2024

the issue will not fix by keepsessioninfo

I did below work around to fix this.

Save the session in _token cookie temporarily. It will not have sameSite property so that you can access it after redirect from apple. Notice I have added a path to this cookie so that it only get send to this path and also maxAge is very short.

      res.cookie('_token', req.session.id, {
        maxAge: 2 * 60 * 1000, // 2 minutes
        httpOnly: true,
        domain: process.env.COOKIE_DOMAIN || '/',
        path: '/v2/auth/apple/callback',
      })

When Apple call us back you can access this _token cookie and load session back. You can use below loadSession middleware in callback route.

function loadAndCreateSession(req: Request, sessionId: string) {
  return new Promise((resolve, reject) => {
    req.sessionStore.load(sessionId, function (err, session) {
      if (err) {
        reject(err)
      } else {
        if (!session?.passport.user) {
          return reject('Failed to get user from session')
        }
        // destroy old session
        req.sessionStore.destroy(sessionId)

        req.logIn(session?.passport.user, () => {
          if (session?.returnTo) {
            req.session.returnTo = session.returnTo
          }
          resolve(session)
        })
      }
    })
  })
}




const loadSession = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const sessionId = req.cookies._token

    if (sessionId) {
      await loadAndCreateSession(req, sessionId)
      res.cookie('_token', '', { maxAge: 0 })
    }
  } finally {
    next()
  }
}

@mifi
Copy link
Contributor

mifi commented Aug 27, 2024

I found a solution to this. As mentioned by others, Apple wants to "think different" and use POST in their callback, however browser's SameSite policy doesn't allow cookies to be included in (POST) requests originating from a different site (in this case Apple). So the session does not exist and the successfuly authentication result (req.login) doesn't get saved anywhere.

A solution is to first redirect the POST request to a GET request, because a GET request can access cookies. And we include all the request body parameters as query params to the GET request:

// initial request, redirects to Apple website
router.get('/apple', passport.authenticate('apple'));

// this is the callback from Apple. Now redirect to GET with query params:
router.post('/apple/callback', express.urlencoded({ extended: true }), (req, res) => {
  const { body } = req;
  const sp = new URLSearchParams();
  Object.entries(body).forEach(([key, value]) => sp.set(key, String(value)));
  res.redirect(`/apple/callback?${sp.toString()}`);
});

// Here we handle the GET request after the redirect from the POST callback above
router.get('/apple/callback', passport.authenticate('apple', {
  successReturnToOrRedirect: '/success',
  failureRedirect: '/failure',
}));

This works even with redirectmeto.com on localhost (without https) now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants