-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
supabase.auth.api.getUserByCookie()
doesn't work in Next.JS server-side environment
#3783
Comments
FYI, this workaroung does the job: let supabase = createClient(supabaseUrl, supabaseKey);
let token = req.cookies['sb:token'];
if (!token) {
return
}
let authRequestResult = await fetch(`${supabaseUrl}/auth/v1/user`, {
headers: {
'Authorization': `Bearer ${token}`,
'APIKey': supabaseKey
}
}); |
Hmm, odd since we're using cross-fetch: https://github.com/supabase/gotrue-js/blob/c213d2f02895248fc8d601a599116531be16071d/src/lib/fetch.ts#L1 I think the middleware is hosted on Cloudflare workers, so the other workaround is here: https://github.com/supabase/supabase/tree/master/examples/with-cloudflare-workers |
I haven't deployed the app yet, so I believe that Cloudflare has nothing do to with it. It's reproducible with local |
Here's an isolated example: https://github.com/vklimontovich/supabase-nextjs-middleware |
Not sure if the same issue or if I'm doing something wrong but: I'm trying to use
BUT! if I check client-side, I do have a user:
|
@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 this @vklimontovich - I see also that you have the buggy code commented out in the example. We have rolled out the fix where you can provide a custom fetch implementation (since cross-fetch isn't working in Cloudflare Workers): https://supabase.io/docs/reference/javascript/initializing#custom-fetch-implementation You should be able to initialise the client like this: import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {
fetch: fetch
}) And after that |
@kiwicopple should that already be working with Next.js's // src/supabaseClient.ts
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY as string;
const supabase = createClient(supabaseUrl, supabaseAnonKey, {
fetch: fetch,
});
export default supabase; I have this simple configuration, but I still get an error that refers to
I have the latest version of supabase (1.28.0). |
Same here @emilioschepis |
I've tested with the updated supabase-js on @vklimontovich 's demo above, and created a PR here: https://github.com/jitsucom/supabase-nextjs-middleware/pull/1/files I can confirm on this PR I'm not seeing this issue any more. Perhaps you can compare with your own implementation to see if there is anything missing? |
Odd. I have this in my _middleware.ts import { supabase } from "@/services/supabase";
import { NextRequest, NextResponse } from "next/server";
export async function middleware(req: NextRequest) {
const {user, token, error} = await supabase.auth.api.getUserByCookie(req)
console.log(error)
... The error is And this is how I export my supabase client import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
if (!supabaseUrl || !supabaseAnonKey)
throw new Error(
"Need to set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY"
);
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
fetch: fetch
}); Running |
Very weird, @kiwicopple's PR didn't work for me as well. I tried to replace custom fetch with: return createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_KEY, {
// @ts-ignore
fetch: (...args) => {
console.log("Args", args)
},
}) And I'm still seeing same error (meaning custom fetch wasn't passed to gotrue-js):
(I did |
Could this be M1 related somehow? |
No. Just tested on my ubuntu desktop and I'm getting the same error. Versions: ❯ yarn info | grep supabase-js -A 8
├─ @supabase/supabase-js@npm:1.28.0
│ ├─ Version: 1.28.0
│ │
│ └─ Dependencies
│ ├─ @supabase/gotrue-js@npm:^1.21.0 → npm:1.21.1
│ ├─ @supabase/postgrest-js@npm:^0.35.0 → npm:0.35.0
│ ├─ @supabase/realtime-js@npm:^1.2.1 → npm:1.2.1
│ └─ @supabase/storage-js@npm:^1.5.0 → npm:1.5.0 |
It sounds like simply importing If that's the case, the above mentioned workaround might be your best bet for now: #3783 (comment) Or you can try the |
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 |
Thanks @kiwicopple . I am also waiting for this to implement the _middleware.ts to our pages that requires SSR for Authentication. |
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? |
Error still occurs in middleware on Next.js dev server. "next": "^12.0.4"
|
If this is the error then you probably want to provide a different Fetch provider: https://supabase.com/docs/reference/javascript/initializing#custom-fetch-implementation |
@kiwicopple it work like a charm in my middleware but somehow i cannot longer fetch the table in the client-side. any idea? export const supabase = createClient(supabaseUrl, supabaseToken, {
fetch,
});
const sessionUser = supabase.auth.user();
const { data: profile } = await supabase
.from('profile')
.select('*')
.eq('id', sessionUser.id)
.single();
console.log('profile :', profile); // always null |
It seems that might be an unrelated issue @yudyananda - you're welcome to start a new issue (so this one doesnt get sidetracked). It could be any of: not authenticated, RLS, |
@yudyananda @kiwicopple I noticed this as well. As a workaround used 2 instances of |
I was suffering from the same issue server side as has been mentioned a couple times here: I found this post on dev.to that solves my problem. OP uses The following is added to the useEffect(() => {
const { data: authListener } = supabase.auth.onAuthStateChange(
(event, session) => {
if (event === "SIGNED_IN") {
updateSupabaseCookie(event, session);
}
}
);
return () => {
authListener?.unsubscribe();
};
});
async function updateSupabaseCookie(event: string, session: Session | null) {
await fetch("/api/auth", {
method: "POST",
headers: new Headers({ "Content-Type": "application/json" }),
credentials: "same-origin",
body: JSON.stringify({ event, session }),
});
} The following is added to const handler = (req: NextApiRequest, res: NextApiResponse) => {
supabase.auth.api.setAuthCookie(req, res);
}; The |
I have another workaround. A one liner 😊
This requires that the cookie is set on auth change like mentioned before :) |
I have the same sort of implementation as this but in a AuthContext and this for me works well with the cookie being set manually |
I'd recommend using https://github.com/supabase-community/supabase-auth-helpers/blob/main/src/nextjs/README.md going forward. |
@thorwebdev Is there a way to refresh the user's token so they aren't logged out after the max expiry of 1 week using the auth-helper? That's the one thing I'm struggling with right now. |
@Murkrage the auth helper library stores the account_token as well as the refresh_token in secure server cookies, and automatically refreshes the account_token when it is expired. This way the user should theoretically never get logged out as the refresh_token doesn't expire. Are you saying you've had issues with that using the auth helpers, or this is a problem you're currently facing not using the auth helpers? NOTE: by default the cookies will expire after 8h. If you want the user to stay logged in longer, you can set the |
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 💚 |
I'm a little confused by this suggestion because the documented example uses the @supabase/ui My 2 cents:
I 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 If anyone can shed some light, I'm eager to understand better, thanks. |
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
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! |
Thanks @thorwebdev, I appreciate the response. Genuinely, Supabase has such a great community and I appreciate the conversation. |
What is the current suggestion if I just want to check for authenticated user in the getServerSideProps (not using next js api for auth) and if I do not prefer to use auth-helpers? |
If 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 |
Just to confirm, this manual work is still needed even when using https://github.com/supabase-community/auth-helpers/tree/main/packages/nextjs#basic-setup correct ? |
Nope, the auth helpers take care of this for you vis the UserProvider component that you wrap your app in. |
Mhh thats interesting because without it the magic link login doesn't work the first time and you need to manually refresh the page or it simply doesnt login at all in production. It's possible that I might be doing something wrong ofcourse. But I'm pretty sure simply using the UserProvider doesnt cover all cases perse |
The magic link redirect will need to go to a page that has the |
@vklimontovich seems like this does not work anymore with the newer version of supabase (1.35.6) |
Nextjs 13 has been released and they provide a new way of fetching data. // app/page.js
import { use } from 'react';
async function getData() {
const res = await fetch('...');
const name: string = await res.json();
return name;
}
export default function Page() {
// This value is fully typed
// The return value is *not* serialized
// so you can return Date, Map, Set, etc.
const name = use(getData());
return '...';
} (taken from here https://nextjs.org/blog/next-13#data-fetching) I have a similar error:
If I try to use another fetch implementation, I get ESM import errors. With node18, it works btw. (still errors, but the page renders and supabase client works) |
Next.js 13 discussion moved -> supabase/auth-helpers#341 |
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:
Add following code to
_middleware.ts
Expected behavior
getUserByCookie() should either work (use
fetch()
internally instead ofXMLHttpRequest
), OR message should be more clear (check the presence ofXMLHttpRequest
ingetUserByCookie()
and throwSorry, 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.
The text was updated successfully, but these errors were encountered: