sidebase / nuxt-auth

Authentication built for Nuxt 3! Easily add authentication via OAuth providers, credentials or Email Magic URLs!
https://auth.sidebase.io
MIT License
1.27k stars 163 forks source link

Login callback error: State cookie was missing. #922

Open julienguillot77 opened 1 week ago

julienguillot77 commented 1 week ago

Environment

Reproduction

  auth: {
    originEnvKey: "NUXT_AUTH_ORIGIN",
    globalAppMiddleware: true,
    provider: {
      type: "authjs",
      trustHost: false,
      defaultProvider: "keycloak",
    },
  },

server/api/auth/[...].ts

  providers: [
    // @ts-expect-error Use .default here for it to work during SSR.
    KeycloakProvider.default({
      clientId: process.env.NUXT_OAUTH_CLIENT_ID,
      clientSecret: process.env.NUXT_OAUTH_CLIENT_SECRET,
      issuer: process.env.NUXT_OAUTH_ISSUER_BASE_URL,
    }),
  ],

.env

NUXT_SESSION_PASSWORD=<session_password>
NUXT_OAUTH_CLIENT_ID=my-app
NUXT_OAUTH_CLIENT_SECRET=<secret>
NUXT_OAUTH_ISSUER_BASE_URL=http://localhost:8180/realms/my-app
NUXT_OAUTH_ADMIN_ENDPOINT_BASE_URL=http://localhost:8180/admin/realms/my-app
NUXT_AUTH_ORIGIN=http://localhost:3000

All my pages are protected with global middleware because this is a management app. So basically if you are not logged in, you are redirected to the Keycloak login page.

http://localhost:8180/realms/my-app/protocol/openid-connect/auth?client_id=management&scope=openid%20email%20profile&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth%2Fcallback%2Fkeycloak&state=ETqYs5Y5hdmv4VuB4HDiS_YFQTtev8ceXNx58R-4okA&code_challenge=O-wdF_AS8EMq-zupG4A9eTDy0raLnRUxZBAHwrqA5UA&code_challenge_method=S256

Describe the bug

You input username and password and should be redirected to the index page of my app.

But it's not the case. I'm redirected to the default login page that next-auth provides.

[next-auth][error][OAUTH_CALLBACK_ERROR] 
https://next-auth.js.org/errors#oauth_callback_error State cookie was missing. { error:
   { TypeError: State cookie was missing.
       at Object.use (/Users/me/Documents/Projects/my-app/management/node_modules/next-auth/core/lib/oauth/checks.js:103:23)
       at oAuthCallback (/Users/me/Documents/Projects/my-app/management/node_modules/next-auth/core/lib/oauth/callback.js:89:25)
       at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
       at async Object.callback (/Users/me/Documents/Projects/my-app/management/node_modules/next-auth/core/routes/callback.js:52:11)
       at async AuthHandler (/Users/me/Documents/Projects/my-app/management/node_modules/next-auth/core/index.js:208:28)
       at async Object.handler (/Users/me/Documents/Projects/my-app/management/node_modules/@sidebase/nuxt-auth/dist/runtime/server/services/authjs/nuxtAuthHandler.js:43:24)
       at async file:///Users/julien/Documents/Projects/my-app/management/node_modules/h3/dist/index.mjs:1978:19
       at async Object.callAsync (file:///Users/me/Documents/Projects/my-app/management/node_modules/unctx/dist/index.mjs:72:16)
       at async Server.toNodeHandle (file:///Users/me/Documents/Projects/my-app/management/node_modules/h3/dist/index.mjs:2270:7)
     name: 'OAuthCallbackError',
     code: undefined },
  providerId: 'keycloak',
  message: 'State cookie was missing.' }

For history purposes, at the beginning of the project, I faced a different error when global auth middleware redirects to the index page of my app (that is secured too and occurs to redirect to Keycloak login page then). After have done some investigations, it was an h3 side issue and a PR has been made and merged.

https://github.com/unjs/h3/pull/888

The PR was merged after I started the project. So the version of h3 that Nuxt depends on is older than the PR change.

I wanted to upgrade Nuxt from 3.10 to 3.12 this morning and the problem appeared at that time. I downgraded to 3.10 but the problem is still there. I think Nuxt depends on the main branch of h3 and not on a particular version. So even if the h3 issue is solved, that have produced a new one.

I think the login callback url does not reads the state cookie correctly but I'm not sure.

Someone has an idea ?

Additional context

The signIn callback URL is :

http://localhost:3000/api/auth/callback/keycloak?state=n0XRuLCKwChA4S4TrObsmmxl3nwxfX2m_1TfNfcFYzs&session_state=d1e70b5e-988c-454a-96ab-084ee294745d&iss=http%3A%2F%2Flocalhost%3A8180%2Frealms%2Fmy-app&code=01021367-44db-4389-8e08-9fdd44f457c0.d1e70b5e-988c-454a-96ab-084ee294745d.01e70eef-93ea-4278-95bd-4e732fde9a48

So the state id is passed through query params but not cookie...

Logs

No response

julienguillot77 commented 1 week ago

After 2 days of headaches, I was able to fix my issue. It was because I provided an empty signIn callback (without returning anything) in the catch-all auth API route... Hope it will help people that face the same issue as me.

julienguillot77 commented 1 week ago

Unfortunately it was a false alarm. At the same time I had overloaded the signIn() method with "undefined" as provider. What is surprising is that with this value (or another string than Keycloak), I do not have the problem. However, the post-logout redirection is not good.

Concerning the state cookie, is it not the library's responsibility to create it? Why is it not created correctly?

zoey-kaiser commented 1 week ago

Hi @julienguillot77 👋

The issue is originating inside NextAuth, which we run under the hood. I did some searching inside their repo and other users have reported this issue too. There is one workaround that was posted, maybe it can resolve your issue?

https://github.com/nextauthjs/next-auth/discussions/7491#discussioncomment-6166539

Dunowen commented 1 week ago

I had the same issue while using Auth0 as a provider and this workaround solved it for me, thank you!

julienguillot77 commented 1 week ago

Hi @julienguillot77 👋

The issue is originating inside NextAuth, which we run under the hood. I did some searching inside their repo and other users have reported this issue too. There is one workaround that was posted, maybe it can resolve your issue?

nextauthjs/next-auth#7491 (comment)

Hello @zoey-kaiser , Thank you for your quick answer. I have already looked at this discussion and to be honest I do not want to apply it because it is a major security flaw. My application is intended for a client who has already suffered attacks in the past and that is why I would like to avoid them suffering again. That said I understand that it is at the level of next-auth that there is a problem. However there is still no definitive fix scheduled yet as everyone just simply disable the checks. Even if they do so, I guess they will only apply fix on their last version right ? We still depend on version 4 if I understand well. Anyway I will write a comment on the issue to ask them kindly to put seriously in consideration a fix.

zoey-kaiser commented 1 week ago

@julienguillot77 I understand the concern. I would recommend you test if the issue is resolved by using https://github.com/atinux/nuxt-auth-utils instead of this package! This package does not depend on NextAuth / AuthJS, which could be the solution here.

julienguillot77 commented 6 days ago

I probably found the reason.

You have to signin from the built-in signin page (or provide yours) to make PKCE and State cookies been created by the library. If you have only one provider, remove the "defaultProvider" from your nuxt.config.ts file and provide the name on the signIn method.

I was not using the signin page and redirect user directly to the Keycloak login page. As a result, cookies cannot be created.