auth0 / nextjs-auth0

Next.js SDK for signing in with Auth0
MIT License
2.01k stars 381 forks source link

Profile (SSR) route fails with "Missing state cookie from login request" on browser tab restoration in chrome #1740

Open aorsten opened 4 months ago

aorsten commented 4 months ago

Checklist

Description

I got this issue in my production app, where users are keeping an authorized page open in Chrome, shutting down their computer, and returning to Chrome again after their session has expired. I have debugged it using puppeteer to view the network tab on initial page load, and it seems that even though the user was on my domain, they immediately start on the auth0 server on one of the endpoint routes there, rather than starting in my application.

I have reproduced it with the example-app from this repository.

Reproduction

  1. Install the example-app and setup the authentication variables required.
  2. In lib/auth0, update the pageRouterAuth by adding a short session duration, and disable rolling - just for easily showing the error.
  session: {
    absoluteDuration: 20,
    // rollingDuration: 3600, 
    rolling: false,
  },
  1. npm run dev
  2. Open google Chrome, and in a new tab visit localhost:3000.
  3. In Chrome, Settings, "On startup" select: "Continue where you left off"
  4. Click into the "Page router" and the "Profile (SSR)" link, and sign in.
  5. Close the Chrome browser.
  6. Wait for more than 20 seconds (the absolute duration of the session) and reopen the browser
  7. Witness how you just get a CallbackHandlerError: Callback handler failed. CAUSE: Missing state cookie from login request (check login URL, callback URL and cookie config)

I am running this in a puppeteer-driven Chrome version, and see in the network tab that even though I am supposed to immediately return to the localhost:3000/page-router/profile-ssr route, I am rather taken on this redirect journey:

  1. Initial request URL to Auth0: https://my-domain.eu.auth0.com/u/login?state=somethingsomething
  2. (i am signed in with microsoft): https://login.microsoftonline.com/common/oauth2/v2.0/authorize?login_hint=&response_type=code&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fmy-domain.eu.auth0.com%2Flogin%2Fcallback&nonce=SOME_NONCE&scope=openid%20profile%20email&state=MORE_STATE
  3. https://my-domain.eu.auth0.com/login/callback?code=VERY_LONG_AUTH_CODE&state=SAME_STATE&session_state=SESSION_STATE
  4. https://my-domain.eu.auth0.com/authorize/resume?state=A_STATE
  5. http://localhost:3000/api/page-router-auth/callback?code=SHORTER_CODE&state=SOME_STATE

So the way I see it, there's little wonder that the state cookie is missing, because how would it have been set if we have never visited my domain first?

Additional context

In my production app I have added error handling in the callback function, to catch these errors and redirect back where I wanted to go originally. But this behavior is a hindrance for a good user experience, in this somewhat edgy case.

nextjs-auth0 version

3.5.0

Next.js version

14.2.3 (and 13.3.0 in my prod app)

Node.js version

18.20.2 (18.12.0 in my prod app)

aorsten commented 4 months ago

Do you have a recommended way to handle this situation? I have no idea why the browser would choose to return to auth0 servers, but Im guessing the session has stored where it went to authenticate - or something like that? Do http redirect codes matter for this?