supabase-js: Nextjs14 with Supabase Auth - AuthApiError: invalid claim: missing sub claim
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
I am trying to setup Supabase authentication using Google Oauth provider. I am following the instructions details in the below link https://supabase.com/docs/guides/auth/server-side/nextjs
I created a login page with a button which calls supabase.auth.signInWithOAuth({ provider: 'google' }
. I see the use being created in Supabase. But when I try to get the session using below code. I get the session as null and the console throws this error AuthApiError: invalid claim: missing sub claim
const supabase = createClient();
const { data: session, error } = await supabase.auth.getSession();
console.log(session);
console.log(error);
AuthApiError: invalid claim: missing sub claim
at handleError (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js:52:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async _handleRequest (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js:89:9)
at async _request (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js:74:18)
at async eval (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/GoTrueClient.js:831:24)
at async SupabaseAuthClient._useSession (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/GoTrueClient.js:754:20)
at async SupabaseAuthClient._getUser (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/GoTrueClient.js:825:20)
at async eval (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/GoTrueClient.js:813:20)
at async eval (webpack-internal:///(rsc)/./node_modules/@supabase/gotrue-js/dist/module/GoTrueClient.js:699:28) {
__isAuthError: true,
status: 401
To Reproduce
- Create a fesh NextJs application
- Follow the instruction at https://supabase.com/docs/guides/auth/server-side/nextjs
System information
- OS: MacOS
- Browser (if applies) Chrome
- Version of supabase-js:
@supabase/supabase-js": "^2.39.8
- Next JS Version:
14.1.3
- Version of Node.js:
v20.10.0
About this issue
- Original URL
- State: open
- Created 3 months ago
- Reactions: 3
- Comments: 25
After 3 days of non-stop debugging I found this: https://github.com/ElectricCodeGuy/SupabaseAuthWithSSR which was a god send I refactored all the code based off this and mixed in some code from the official docs and it seems to be working now, some tips I’ve gathered along the way, and what I did
middleware.ts
file is in root (/src or your equv)persistSession: false
when creating the SB client but i did not - the only time i did this was when i required using my service_role key when calling SB from a stripe webhookother things I did along the way which I’m not sure contributed to me getting it working but adding here for completeness
next dev --turbo
here’s my code for reference:
auth/callback/route.ts
middleware.ts
util/supabase/server.ts
util/supabase/client.ts
Google auth button component
May also be worth noting that when I created a SB client for my service_role key, I did it this way
not using the @supabase/ssr package
P.S. Am just a junior dev so apologies in advance if any of this isn’t sound advice
Authentication seems to be broken atm. My linkedIn auth provider was broken yesterday, a fix was put out for that this morning. But google Auth provider is broken too. getting this error data: { user: null }, error: AuthApiError: invalid claim: missing sub claim at handleError (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/lib/fetch.js:62:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async _handleRequest (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/lib/fetch.js:116:9) at async _request (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/lib/fetch.js:92:18) at async eval (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/GoTrueClient.js:1064:24) at async SupabaseAuthClient._useSession (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/GoTrueClient.js:949:20) at async SupabaseAuthClient._getUser (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/GoTrueClient.js:1058:20) at async eval (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/GoTrueClient.js:1041:20) at async eval (webpack-internal:///(rsc)/./node_modules/@supabase/auth-js/dist/module/GoTrueClient.js:897:28) { __isAuthError: true, status: 403, code: ‘bad_jwt’
my callback route looks like this ` 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’) ?? ‘/’ console.log(‘code:’, code)
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 }) }, }, } ) const { error } = await supabase.auth.exchangeCodeForSession(code) if (!error) { return NextResponse.redirect(
${origin}/dashboard
) } console.log(error); }// return the user to an error page with instructions return NextResponse.redirect(
async function signInWithGoogle() { const supabase = supabaseBrowser(); const { error } = await supabase.auth.signInWithOAuth({ provider: ‘google’, options: { queryParams: { access_type: ‘offline’, prompt: ‘consent’, }, redirectTo:
${origin}/auth/auth-code-error
) }${window.location.origin}/auth/callback
, } }); if (error) { console.error(‘Error signing in:’, error); } } ` It sucessfully creates the user, but and logs in but when i try to fetch userId or session i run into the prescribed errorYeah, its slowing down my development process. The linkedIn one wasnt supabase’s fault tbf, LinkedIn had release a breaking change without communicating it and that causes linkedIn auth to be broken. But the fix for that was merged this morning so it might take a while before that gets rolled out. But then my Google auth had also been broken.
Can u send me sample code of your auth/callback/route.ts ?
Thank you!
@pdomala ok i figured out, you have to have a auth/callback/route to handle the
code
thingyawait supabase.auth.exchangeCodeForSession(code);
Adding my sample repo with Supabase where the error can be re-produced. https://github.com/pdomala/nextjs14-supabase-sample