supabase / auth

A JWT based API for managing users and issuing JWT tokens
https://supabase.com/docs/guides/auth
MIT License
1.51k stars 369 forks source link

Flow State not found #1341

Open Phil9l opened 10 months ago

Phil9l commented 10 months ago

Bug report

Describe the bug

I am using self-hosted supabase with gotrue and next js for auth. A few users can't login to the app because they get redirected to the following page every time they try to sign in with google.

[GET] /auth/callback?next=%2F&error_description=Flow%20State%20not%20found&error=server_error status=307

I haven't found anything unusual about these users.

On the client side I call

            const { error } = await supabase.auth.signInWithOAuth({
              provider: "google",
              options: {
                redirectTo: `${window.location.origin}/auth/callback?next=${window.location.href}`,
                queryParams: {
                  access_type: "offline",
                  prompt: "consent",
                },
              },
            });

To Reproduce

I haven't found why it happens to these specific users. They are using mobile chrome and using the same auth flow as other users. They tried logging in using multiple different google accounts.

  1. Go to https://climbest.app/
  2. Click on login
  3. Be lucky I guess?
  4. Get redirected to the Flow State not found error.

Expected behavior

Users can log in to the app.

Screenshots

https://imgur.com/a/D9WGyMH

System information

hf commented 10 months ago

What libraries do you use with NextJS? Please send us a code snippet that includes the initialization of the Supabase client.

Phil9l commented 10 months ago

What libraries do you use with NextJS?

    "@supabase/ssr": "^0.0.4",
    "@supabase/supabase-js": "^2.39.0",

Please send us a code snippet that includes the initialization of the Supabase client.

I'm initializing the client like this:

import { createBrowserClient } from "@supabase/ssr";

const supabase = createBrowserClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

And using like this:

const { error } = await supabase.auth.signInWithOAuth({
  provider: "google",
  options: {
    redirectTo: `${window.location.origin}/auth/callback?next=${window.location.href}`,
    queryParams: {
      access_type: "offline",
      prompt: "consent",
    },
  },
});

I think I copy-pasted code from https://supabase.com/docs/guides/auth/server-side/oauth-with-pkce-flow-for-ssr to my climbclimb/src/app/auth/callback/route.ts:

import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { type CookieOptions, createServerClient } from "@supabase/ssr";

export async function GET(request: Request) {
  const { searchParams, origin } = new URL(request.url);
  const code = searchParams.get("code");
  // if "next" is in param, use it as the redirect URL
  const next = searchParams.get("next") ?? "/";

  if (code) {
    const cookieStore = cookies();
    const supabase = createServerClient(
      process.env.NEXT_PUBLIC_SUPABASE_URL!,
      process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
      {
        cookies: {
          get(name: string) {
            return cookieStore.get(name)?.value;
          },
          set(name: string, value: string, options: CookieOptions) {
            cookieStore.set({ name, value, ...options });
          },
          remove(name: string, options: CookieOptions) {
            cookieStore.delete({ name, ...options });
          },
        },
      }
    );

    try {
      if (!code) {
        throw new Error(
          `code param is missing in ${
            request.url
          }; all params: ${JSON.stringify(searchParams)}`
        );
      }
      const { error } = await supabase.auth.exchangeCodeForSession(code);

      if (!error) {
        return NextResponse.redirect(`${next}`);
      } else {
        console.error(error);
        return NextResponse.redirect(`${origin}/?error=${error.message}`);
      }
    } catch (error: unknown) {
      console.log(error);
      if (error instanceof Error) {
        return NextResponse.redirect(`${origin}/?error=${error.message}`);
      } else {
        return NextResponse.redirect(`${origin}/?error=${error?.toString()}`);
      }
    }
  }

  // return the user to an error page with instructions
  return NextResponse.redirect(`${origin}/auth/auth-code-error`);
}
nonnster commented 9 months ago

I'm also experiencing the same thing. Some of my google user aren't able to login because of the same problem. @Phil9l were you able to get around this issue?

Phil9l commented 9 months ago

I'm also experiencing the same thing. Some of my google user aren't able to login because of the same problem. @Phil9l were you able to get around this issue?

No, unfortunately, not. More and more users are complaining about it. It's getting pretty critical for us at this point.

hf commented 9 months ago

If you are able to reproduce, please send us a HAR recording if possible. You can use https://supabase.help if you want to keep that private, just mention this issue when opening a support ticket.

Some causes of why the error could be happening:

  1. Cookie chunking issues -- mobile browsers may be having trouble dealing with larger / multiple cookies.
  2. Requesting sign-in from one browser receiving the callback on another. (When using PKCE the sign-in should complete on the same browser it was started on.)
  3. The cycle takes too long. Right now this is 300 seconds.

As you mentioned self-hosting, please provide us with details of the versions you're using on the server and configuration options related to this.

hnykda commented 8 months ago

We have seen that too, but only occasionally and I cannot reproduce that (hence can't share more than just these):

TypeError: Cannot read properties of undefined (reading 'call')
    at Object.__webpack_require__ [as require] (/var/task/.next/server/webpack-runtime.js:1:161)
    at /var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:111:463
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async rs (/var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:110:4701)
    at async rT (/var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:111:27761)
    at async ee (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:24526)
    at async en.responseCache.get.incrementalCache (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:991)
    at async rW.renderToResponseWithComponentsImpl (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:448)
    at async rW.renderPageComponent (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:4990)
    at async rW.renderToResponseImpl (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:5573)
[POST] /auth/login?error=server_error&error_description=Flow%20State%20not%20found&next=%2Fquestion-suggestion status=500

image

JeronimasDargis commented 5 months ago

Hey, I am experiencing the same issue. I got this callback URL, unable to replicate it on my side. It was spotted on Pagesense logs.

#error=server_error&error_code=422&error_description=Flow+state+not+found

jayhickey commented 5 months ago

We're also seeing this, it's happening 20-40 times a day for our users. Redirect looks like this:

/error?error=server_error&error_code=422&error_description=Flow+state+not+found&message=Missing+cod
e#error=server error&error code=422&error_description=Flow+state+not+found
Forsect commented 5 months ago

Same for us, didn't see any issue like for months, started to happening last week...

Jaaneek commented 5 months ago

Same for us, google oauth suddenly doesn't work 30% of the time.

Mostly for mobile users but also happens on Desktop.

gvzq commented 4 months ago

We're noticing this same trend in our project using Google Auth. I would greatly appreciate if Supabase can provide us with some guidance.

bookerlyio commented 4 months ago

I'm getting this when trying to confirm emails using a callback url

const { error } = await supabase.auth.exchangeCodeForSession(code);

xeladotbe commented 4 months ago

I have the same problem, as auth-code a uuid v4 is expected, but from the provider I only get back a code (i.e. ANbOebvxVXCktJlSDXTU) which is not found in the DB (obviously), I don't know where the uuid v4 should come from that is searched for in https://github.com/supabase/auth/blob/master/internal/api/token.go#L258

J0 commented 3 months ago

Hey team(s),

Thanks for flagging this and for patiently waiting. Flow State not found typically indicates that one should restart the flow as the internal db representation containing the matching code doesn't seem to exist. It tends to be a generic error which can arise for a spread of reasons. We're looking to see if there's a common overarching cause though.

With respect to the individual queries could we trouble everyone for a few information.

I have the same problem, as auth-code a uuid v4 is expected, but from the provider I only get back a code (i.e. ANbOebvxVXCktJlSDXTU) which is not found in the DB (obviously), I don't know where the uuid v4 should come from that is

For clarity, the Auth Code in this case is returned by Supabase Auth and not the OAuth provider (e.g. Google). It's returned as a param ?code=<...> once the call to supabase.auth.signInWithOAuth has completed. Could you try using the code returned from signInWithOAuth or similar and let us know if there are any issues?

We're noticing this same trend in our project using Google Auth. I would greatly appreciate if Supabase can provide us with some guidance. Same for us, didn't see any issue like for months, started to happening last week... We're also seeing this, it's happening 20-40 times a day for our users. Redirect looks like this:

Would the respective team(s) be able to provide additional reproduction steps for this? If there's sensitive information feel free to open a ticket via our support line

Thanks! Let us know if there are any pressing concerns.

J0 commented 3 months ago

Hey @Jaaneek

Thanks for the report - do you recall if there's a specific reproducible scenario where this happens? We'd like to dig in further.

Same for us, google oauth suddenly doesn't work 30% of the time. Mostly for mobile users but also happens on Desktop.

kor-bim commented 3 months ago

help same issue, kakao provider too --- i handle it

In my case, the error occurred because Nginx received a header from Google that was too large to process

msssrp commented 3 months ago

~help same issue, kakao provider too~ --- i handle it

In my case, the error occurred because Nginx received a header from Google that was too large to process

In my case this works. You just saved my life thank you.

hotay commented 3 months ago

We recently discovered that users clicked twice on the Google OAuth confirmation page, causing issues. The first click successfully triggers Supabase's /callback, but the second click fails because /callback deletes the flow state ID after the initial successful call.

By the way, I'm using the Supabase cloud not self-hosted.

@J0

J0 commented 3 months ago

Thanks @hotay this is useful

kirkstrobeck commented 3 months ago

After supabase.auth.exchangeCodeForSession I returned a page that performed a redirect, when I just return return NextResponse.redirect(requestUrl.origin); the problem goes away. I suspect its a race condition with setting/reading the cookie

chris-feist commented 2 months ago

What I realized was happening in my case is that during sign up, resource creation was taking longer than 5 seconds, so the oauth callback was retried. The retried request always failed with this error since I assume the code was already read/processed. I'm using Remix, so I ended up running async functions in parallel to speed up my loader and using Streaming for a better UX.