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?