I'm using supabase-js client library to handle GitHub OAuth authentication in my nextjs 13 frontend app:
// Login with GitHub
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github'
})
U nder the hood this is making an GET request to supabase's /auth/v1/user endpoint of my supabase instance with the supabase-provided api key already in the header.
This operation results in a 401 Unauthorized error:
GET https://<instance>.supabase.co/auth/v1/user 401 (Unauthorized)
{
"error": "invalid claim: missing sub claim"
}
The issue seems to be that the API_KEY JWT used by signInWithOAuth() is missing the expected sub claim, causing subsequent auth API requests to fail. But the weird thing this is the API key provided by supabase. Using both the anon public and service_role secret provided by supabase return this error for that endpoint. Both are JWTs that do not contain a sub field when decoded.
Debugging steps:
- Confirmed API_KEY works for non-auth REST endpoints like
/<not-user>/* - Verified OAuth flow returns valid GitHub access_token - which contains a sub field
- Checked for expiration or reuse issues
- I using managed free tier supabase and not a self-hosted or premium version.
Issues I have looked at:
- https://github.com/supabase/supabase/issues/13095
- https://github.com/orgs/supabase/discussions/12400
Also, it appears in supabase the gotrue JWT encoding library may be involved according to this issue:
if claims.Subject == "" {
return nil, unauthorizedError("invalid claim: missing sub claim")
}
This suggests the problem could lie in how Supabase encodes and signs JWTs returned by signInWithOAuth(), rather than the GitHub access token itself.
...
Any thoughts on why supabase would provide an API_KEY missing sub for OAuth and then go on to error out with a 401 when requested using the same API key?



subclaim. The error might be talking about the token obtained from Github. I would double check every steps you took to setup the Github app that is connected to your Supabase instance. supabase.com/docs/guides/auth/social-login/auth-github.getUser()is being called. If this is from the NextJS template we've created it's due to the.getUser()call inside of theapp/page.tsxfile.jwttoken to be available(or be created from) forgetUserto request for user. @AndrewSmith Thanks