supabase: `supabase.auth.api.getUserByCookie()` doesn't work in Next.JS server-side environment
Bug report
Describe the bug
supabase.auth.api.getUserByCookie()
doesn’t work in Next.JS server-side environment (_middleware.ts
)
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
- Create a supabase project
- Create a Next.JS project
- Create
Add following code to _middleware.ts
export async function middleware(req: NextRequest, ev: NextFetchEvent) {
let supabase = createClient(...);
let user = await supabase.auth.api.getUserByCookie(req);
console.log('Auth ', user)
}
- See logs
Auth {
user: null,
data: null,
error: ReferenceError: XMLHttpRequest is not defined
at eval (webpack-internal:///./node_modules/cross-fetch/dist/browser-ponyfill.js?d2fb:462:17)
at new Promise (<anonymous>)
at fetch (webpack-internal:///./node_modules/cross-fetch/dist/browser-ponyfill.js?d2fb:455:12)
at eval (webpack-internal:///./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js?85f4:44:63)
at new Promise (<anonymous>)
at eval (webpack-internal:///./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js?85f4:43:16)
at Generator.next (<anonymous>)
at eval (webpack-internal:///./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js?85f4:16:71)
at new Promise (<anonymous>)
at __awaiter (webpack-internal:///./node_modules/@supabase/gotrue-js/dist/module/lib/fetch.js?85f4:12:12)
}
Expected behavior
getUserByCookie() should either work (use fetch()
internally instead of XMLHttpRequest
), OR message should be more clear (check the presence of XMLHttpRequest
in getUserByCookie()
and throw Sorry, you shouldn't call this method in server side environment
System information
Next version is 12.0.1
Additional context
Add any other context about the problem here.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 6
- Comments: 43 (18 by maintainers)
FYI, this workaroung does the job:
I was suffering from the same issue server side as has been mentioned a couple times here:
getUserByCookie()
returnsnull
even though the client returns a user as expected. I’m using a magic link as my login method and what I noticed was that my session cookie wasn’t set.I found this post on dev.to that solves my problem. OP uses
supabase.auth.onAuthStateChange()
andsupabase.auth.api.setAuthCookie()
to manually set the supabase cookie client side. Once that’s happened the server correctly fetches the user.The following is added to the
_app.tsx
:The following is added to
/api/auth.ts
:The
supabase.auth.api.XXX
methods aren’t documented anywhere. As far as I can tell at least. It seems to do the trick, though. Not sure if this is the desired implementation, would love to get feedback on this.after more thorough testing I found the error was persisiting. sorry about the false posititve.
I added another commit to the PR, based on Thor’s link to the cross-fetch package - in particular, this comment. I can confirm that this works in Next.js middleware, on a local environment.
I’ll follow up on the linked package and see if that change is OK to merge
I’d recommend using https://github.com/supabase-community/supabase-auth-helpers/blob/main/src/nextjs/README.md going forward.
@saltcod have you set server cookie from client-side code? We published a post today, with a step-by-step guide on how to make next.js middleware work with Supabase auth: https://jitsu.com/blog/supabase-nextjs-middleware
Thanks for the feedback @IHIutch, I understand your frustration, a bunch of things are in flux atm which creates this less than ideal experience 😞
Not at all a requirement. The Auth UI Element is solely meant to make things faster/easier by giving you a prebuilt UI, but not at all a requirement. You can always built your custom UI if you prefer.
It’s technically not an issue, or at least not a bug, since you very well can set the cookies yourself if you want. It’s just not the easiest thing to do. So having some convenience libraries to help you with this is our philosophy here.
Again, all of these are optional and are meant as a convenience. the
@supabase/auth-helpers
are non-ui helpers and the@supabase/auth-ui
(https://github.com/supabase-community/auth-ui) is where the Auth UI Elements will be moved to in the future.It does, have a look at the example here: https://github.com/supabase-community/auth-helpers/blob/main/examples/nextjs/pages/middleware-protected/_middleware.ts
Sorry, we’re working on improving this experience, just a lot of moving parts right now. We really appreciate your feedback and will use it to improve things!
I’m a little confused by this suggestion because the documented example uses the @supabase/ui
Auth
which I’ve found tends to obfuscate what is actually happening when authenticating. I appreciate that this community package appears to solve some issues (Does it actually solve the _middleware issue? I’m not seeing that confirmed anywhere) but I still feel a bit in the dark on some other things.My 2 cents:
Auth
when handling auth when using Supabase? That feels odd to me./api/auth/register
route to create a user in my DB and sign them in. It’s unclear to me how I’d do that using the community packageI don’t mean to offend, I’m an intermediate developer at best, I’m just trying to understand and leverage the incredible framework that is Supabase. But as such, I’m really struggling to understand the solution here. My app works fine, with everything except
getUserByCookie
when using_middleware
, so this feels like an additional piece of complexity to understand and keep up with as things change.If anyone can shed some light, I’m eager to understand better, thanks.
Closing this out, as mentioned, please use https://github.com/supabase-community/supabase-auth-helpers/blob/main/src/nextjs/README.md going forward and open issues there if you encounter any. Thanks 💚
@yudyananda @kiwicopple I noticed this as well. As a workaround used 2 instances of
SupabaseClient
: one for client side (without custom fetch) and one for server side with this PR applied.@kiwicopple should that already be working with Next.js’s
fetch
?I have this simple configuration, but I still get an error that refers to
cross-fetch
when checking the auth in a middleware function.I have the latest version of supabase (1.28.0).
I haven’t deployed the app yet, so I believe that Cloudflare has nothing do to with it. It’s reproducible with local
next dev
. I’ll try to make an isolated example and maybe suggest a patchIf you prefer not to use the helpers, you would probably want to follow the same process in the helpers code. eg: set the Auth token inside a cookie, and then extract the value of the cookie inside
getServerSideProps
- the idea of the helpers isn’t to do anything unique, it’s simply to provide a library which will follow the same steps that you’d do yourselfThanks @thorwebdev, I appreciate the response. Genuinely, Supabase has such a great community and I appreciate the conversation.
supabase.auth.api.getUserByCookie(req) doesn’t work in getServerSideProps (only in production for me either).
I’ve tried so many things, including what the OP wrote in this article here.
Any updates on this?
Very weird, @kiwicopple’s PR didn’t work for me as well. I tried to replace custom fetch with:
And I’m still seeing same error (meaning custom fetch wasn’t passed to gotrue-js):
(I did
rm -rf node_modules && rm -rf yarn.lock && yarn install
to make sure all packages are uptodate)Here’s an isolated example: https://github.com/vklimontovich/supabase-nextjs-middleware