auth-helpers: invalid request: both auth code and code verifier should be non-empty
Bug report
- I confirm this is a bug with Supabase, not with my own application.
- I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
When calling auth.exchangeCodeForSession(code) this error is thrown:
AuthApiError: invalid request: both auth code and code verifier should be non-empty
at /Users/k/git/myrepo/node_modules/@supabase/gotrue-js/dist/main/lib/fetch.js:41:20
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
__isAuthError: true,
status: 400
To Reproduce
Login callback handler:
const code = event.url.searchParams.get('code')
if (typeof code === 'string') {
const { data, error } = await event.locals.supabase.auth.exchangeCodeForSession(code)
}
This is how I’m starting the login:
const supabaseAnonPkce = createClient<Database>(
PUBLIC_SUPABASE_URL,
PUBLIC_SUPABASE_ANON_KEY,
{
auth: {
flowType: 'pkce',
},
}
)
const { error } = await supabaseAnonPkce.auth.signInWithOtp({
email,
})
Expected behavior
- It seems like an unexpected error since it mentions a “code verifier”, so I’m guessing it’s not supposed to happen
- Errors should be returned in the
errorproperty, not thrown.
Screenshots
If applicable, add screenshots to help explain your problem.
System information
- OS: macOS
- Browser: Brave 1.51.114, Chromium 113.0.5672.92
- Version of supabase-js: 2.21.0
- Version of Node.js: 18.15.0
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 32
- Comments: 63 (15 by maintainers)
I’m still facing the issue. Followed the documentation https://supabase.com/docs/guides/auth/auth-helpers/sveltekit#server-side and I’m trying server side authentication.
Supabase auth logs are showing the same:
{“component”:“api”,“error”:“400: invalid request: both auth code and code verifier should be non-empty”,“level”:“info”,“method”:“POST”,“msg”:“400: invalid request: both auth code and code verifier should be non-empty”,“path”:“/token”,“referer”:“”,“remote_addr”:“<ip-addr>”,“time”:“2023-07-09T11:21:32Z”,“timestamp”:“2023-07-09T11:21:32Z”}
I played with this in the debugger and found a reliable repro. The blog post also confirms the following flow:
signInWithOTPgets called with a redirect, usually the project’s/auth/callbacksb-<project ID>-auth-token-code-verifier/auth/callbackwith thecodequery param“Another client” cold mean an incognito window, another browser, another device, etc. E.g. someone initiated sign in from the browser on a desktop, then open the magic link from a mobile email app. Or initiated from the main browser app, but continued in a webview with a separate cookies store.
If I understand correctly, the code verifier shouldn’t leave the client (that’s the whole point of PKCE). So the fix here would just be failing gracefully from Supabase/GoTrue, and let the project display a recovery path. Something shorter than
Workaround for now is to catch it (as it’s not returned via
result.error)Edit: Example with screenshots and code added here: https://github.com/supabase/auth-helpers/issues/545#issuecomment-1666960329
I am also seeing this with using google oauth. Our initiation of the auth flow is on the client and I am seeing this error on the server, not sure if that is important.
Issue for me is with email confirmation flow not oauth. Works fine locally. Should point out, it seems to actually confirm the email but throws an error.
This is happening on Vercel and it’s kicking out:
For now, I have worked around this simply by suppressing the offending function. This obviously isn’t an ideal situation though:
Looks like the problem still continues for signInWithOAuth in nextjs@13.4.19. @silentworks
with the same code not getting any error if i use nextjs@13.4.7
client component
app/auth/callback/route.js
Nope. Still struggling with this… 😦
Here’s a possible flow. More code but better UX imo.
No client JS needed in this example. Should work with SSR and SSG.
As mentioned above, missing cookie/clicking from a different device is a normal case that should be handled imo.
Screenshots here. Code below.
Flow
Present login options

Show a quick tip after sending magic link

Green path: home page; missing cookie (this issue): show recovery options. Optionally, show other ways to login, e.g. password

Bonus (unrelated to this issue). If the link has been clicked or expired, return to login page with a message:

These messages can probably be improved if you work with a design team.
Code
Update your login page support the above layouts. For example, use a
typequery param with these values:diff_devicebad_codesent_magic_link(optional)Update the
emailRedirectTofield when handling the “Sign in with magic link” button click. You can do this on the client or the server.Example route handler in Next.js:
Bit more complicated to maintain but worth it for the overall UX imo.
Should work with other SSR/SSG frameworks too since the above doesn’t need any client-side JS.
Share here if you found better ways 🙌
@silentworks To avoid confusing the original issue here, I’ve created https://github.com/supabase/auth-helpers/issues/549. The issue seems to be related to
exchangeCodeForSessionexpectinguser_idto be set in the flow state. It’s unclear to me how that would be, since this is the initial login, so no user has been created yet.I am running into this with
createRouteHandlerSupabaseClient(which is the same as createServerComponentSupabaseClient) that only takesheadersandcookies, maybe something is lacking there?I’m going to close this issue again until someone actually provides an reproducible example repo as I’ve showed in my recording and examples I’ve linked. This is working but folks keep on adding on here I have the same issue without any reproducible examples.
@edgarasben but
signInWithOAuthdoesn’t use email templates. You would still just have both endpoints in your project.i’m also experiencing this error when i try to use the remix auth helpers following the official guide here.
using:
supabaseClient.auth.signInWithOtpwith auth email settings:
auth works fine out of the box with this remix stack, but i’d like to switch to the official remix helpers.
Turns out I need to upgrade to the latest version of Node 18.x: https://github.com/vercel/next.js/issues/52209#issuecomment-1621889571
@silentworks, Is this mentioned anywhere in the docs? I spent pretty much all day today trying to get OAuth to work in SSR mode on a NextJS project with a refine.dev template and coming across this information earlier would have been incredibly helpful!
Also, the naming is rather misleading -
auth-helpersstrikes more as an add-on to supabase-js and not so much a replacement.Is there a way to use PKCE easily with Cloudflare Workers? We’ve been using
createClient(from@supabase/supabase-js) and it’s been working great, until trying to add PKCE.@probablykasper I’m going to make a big ask of you, but can you create a minimal reproducible example repo that I can take a look at please?
The issue in the code seems to be the use of two different clients. You are using the auth helpers along with the normal supabase client, this won’t work and will result in the error you are getting. We have a branch of the auth-helpers with PKCE support that you should use until we make the final release. You can install this using:
You shouldn’t mix the auth-helpers client with a normal supabase-js client unless you are planning to do things with the
service_rolekey. There is an example project using these at the moment in this repo https://github.com/supabase-community/supabase-by-example/tree/next/magic-link/sveltekit. We will be releasing the next version of the auth-helpers with full support soon. Currently we are just finalising the documentation for release.