#Vercel serverless Node.js API (NOT Next.js) can't auth user with Supabase

23 messages · Page 1 of 1 (latest)

vagrant hatch
#

supabase-js version: 2.0.4
using Vite (not create-react-app) if that makes a difference.

I'm trying to build an API using Vercel serverless functions (NOT a Next.js API). I can't seem to be able to retrieve the user object from within the API handler. I'm not sure what I'm doing wrong and I see no meaningful error message in the returned error object or the Supabase log. This is the error object:

error:  AuthApiError: Internal server error
    at C:\XXX\node_modules\@supabase\gotrue-js\src\lib\fetch.ts:41:16
    at processTicksAndRejections (node:internal/process/task_queues:95:5) {
  __isAuthError: true,
  status: 500
}

The Supabase event that appears to be raised by the call (what is invalid claim: subject missing?):

{"component":"api","error":"invalid claim: subject missing","level":"error","method":"GET","msg":"Unhandled server error: invalid claim: subject missing","path":"/user","referer":"","remote_addr":"xxx.xxx.xxx.xxx","time":"2022-10-29T19:23:01Z","timestamp":"2022-10-29T19:23:01Z"}

And the code in the API handler:

const supabaseClient = createClient(supabaseUrl, supabaseKey);

const user = await supabaseClient.auth.getUser();

user is null and user.error contains the information pasted above.

I have no problem with auth in a Next.js API using createServerSupabaseClient from the auth-helpers-nextjs package.

Looking at the cookies, after authentication in the browser a cookie containing a JWT gets set in local storage. But the browser does not send that cookie along when requesting the API endpoint. The request headers do not contain the cookie. So I guess the API handler can't verify the user since there is nothing to verify.

I have no idea what's going on. Is this a bug or am I missing something obvious?

still pine
#

This is a Next.js server.. wouldn't this be better to ask in the supbase server?

#

Oh sorry I see, you are using the serverless functions

#

So this question is about running supabase-js code within edge functions?

#

I have a guess as to why it is failing

#

I think that the default behaviour of supabase to persist a session could get in the way since there is no localStorage on vercel edge functions.

const supabaseClient = createClient(supabaseUrl, supabaseKey, {
      auth: {
        persistSession: false,
      }
});
vagrant hatch
#

Nice to meet you again @still pine 🙂

I'm actually using regular non-edge serverless functions on Vercel. I would post to a general "Vercel" server but I couldn't find any, so I had to resort to posting to the Next.js Discord (posted the same message on Supabase Discord).

So looking at the supabase-js source code I found out that createClient does not create a cookie, and I think this is why the browser doesn't send anything to the API. auth-helpers-nextjs has a wrapper around createClient that takes care of creating that cookie. Then there is another wrapper server side that parses the cookie and the JWT.

So it looks like I have to implement my own wrappers that write/read the cookie. I don't know why this cookie handshake isn't provided out of the box by Supa in a more generic way that doesn't depend on using Next or Remix or SvelteKit. Unless I'm missing something obvious.

#

(in case you want to chime in there)

still pine
#

As I said, by default supabase-js stores the token in localStorage. You can customize createClient the same way that it is done in the auth helpers.

#

Did you try to not persist the cookie?

vagrant hatch
still pine
#

But you are running this createClient call in a serverless funciton?

vagrant hatch
still pine
#

You can't wrap loaders in functions and expect remix to be able to extract that code for the client bundle.

#

When a user logs in I send the token to the server, and it creates a cookie.

#

The issue with next.js auth helpers, is that the v2 ones use cookies now, but they aren't http only anymore. I think that is too bad.

vagrant hatch
# still pine But you are running this `createClient` call in a serverless funciton?

both on the browser and in the serverless function. The browser call doesn't persist the cookie if I set the option to false (obviously) so I suppose the browser doesn't sent the API endpoint anything.

So what you did is create a special endpoint in your API to receive the cookie? And then you create another cookie on the browser and send that to the server to be matched up?

still pine
#

For provider auth (which is what I focus on) when the user is redirected back to my site, I can't capture that redirect on the server. Supabase only supports accepting that token on the client. So I get the token on the cilent and send it to the server. Server stores a cookie, and then it creates a client using the access_token whenver it needs it on the client or server.

vagrant hatch
#

Ok I'll check out your source code! Thx

still pine
#

I'll warn you, I haven't implemented refresh yet, I'll be doing that as soon as I get a break from work.