Closed dukesx closed 7 months ago
If anyone encounters this issue, here is the solution: https://www.youtube.com/watch?v=PdmKlne1gRY and Supabase, PLEASE, before you ask devs to migrate to new packages, make sure you have COMPLETE documentation and resources laid out.
Also came across this issue and was confused as to why this wasn't working. I also tried the above solution without any luck.
Originally defined the signout function in the component with the "user server"
like in the above video
something like the following
export default async function LoginPage() {
const cookieStore = cookies()
const supabase = createClient(cookieStore)
const { data, error } = await supabase.auth.getUser()
async function logout(event: Event) {
"user server"
await supabase.auth.signOut()
}
return data?.user ? (
<>
<p>Hello {data.user.email}</p>
<form action={logout}>
<button>Logout yall</button>
</form>
</>
) : (
<form>
<label htmlFor='email'>Email:</label>
<input id='email' name='email' type='email' required />
<label htmlFor='password'>Password:</label>
<input id='password' name='password' type='password' required />
<button formAction={login}>Log in</button>
<button formAction={signup}>Sign up</button>
</form>
)
}
This still confused Next. I think problem is you can't define a server running function within a server component. All I had to do was move my logout function outside the component.
If you're following along with the SSR next auth tutorial here, I just added it to the app/login/actions.ts
page
...
export async function signup(formData: FormData) {
const cookieStore = cookies()
const supabase = createClient(cookieStore)
// type-casting here for convenience
// in practice, you should validate your inputs
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
}
const { error } = await supabase.auth.signUp(data)
if (error) {
redirect('/error')
}
revalidatePath('/', 'layout')
redirect('/')
}
export async function logout() {
const cookieStore = cookies()
const supabase = createClient(cookieStore)
await supabase.auth.signOut()
revalidatePath('/', 'layout')
redirect('/auth')
}
And then in my auth/page.tsx
import { login, signup, logout } from './actions'
import { cookies } from 'next/headers'
import { createClient } from '@/utils/supabase/server'
export default async function LoginPage() {
const cookieStore = cookies()
const supabase = createClient(cookieStore)
const { data, error } = await supabase.auth.getUser()
return data?.user ? (
<>
<p>Hello {data.user.email}</p>
<form action={logout}>
<button>Logout yall</button>
</form>
</>
) : (
<form>
<label htmlFor='email'>Email:</label>
<input id='email' name='email' type='email' required />
<label htmlFor='password'>Password:</label>
<input id='password' name='password' type='password' required />
<button formAction={login}>Log in</button>
<button formAction={signup}>Sign up</button>
</form>
)
}
Maybe super obvious in hindsight, but I didn't find it clear why the above wasn't working for me originally. Maybe this is helpful to someone.
@hydenp I just followed the same Server-Side Auth Next.js instruction from Supabase but am having an issue that my sb-localhost-auth-token
cookie is not being set. This means that even though I authenticate without issue, because the cookie is never set, I can't getUser or getSession successfully any of the places that they do in the tutorial.
I notice that you are doing something different from the tutorial, which is that you are passing the cookies into createClient
instead of doing that in utils/supabase/server
like they do in the tutorial. Is there a reason for that?
I've literally copy and pasted from the tutorial and am having this major problem, so wondering if you had to do anything else to get this to work for you?
@jj0b , I'm not sure if this will be helpful, but I'd like to share my experience. Initially, I was creating a constant outside and calling it in every function to simplify the code. The constant was defined as follows ( as a global variable) :
const supabase = createClient();
However, I realized that this approach was incorrect. It seems that you need to create it every time you create an action. This solution fixed the issue for me. It’s possible that this information was included in the documentation, but I may have overlooked it. I hope you find this information useful.
@DAGGE3R thank you. Yes, I did see it in the docs here that you need to create the client anew for every request to the server because it needs the cookies for the request.
I think this explains why @hydenp was passing the cookieStore
to createClient
, but in the Supabase tutorial I linked they just create the client from scratch in multiple different places.
Turns out my issue was simply that I was using the domain 127.0.0.1
in my callback url instead of localhost
which is where I was running my app. Even though that IP resolves to the same thing, it meant that my cookie was being written to the wrong domain. Once I updated my callback url to be at localhost
everything worked.
EDIT: I'm new to app router and wasn't understanding a core concept of it, so I've fixed this issue. If you're like me and prefer to have a /logout
route that logs the user out and redirects them, then make sure to put that into a router handler, NOT a page. This is all you need.
app/logout/route.ts
import { createClient } from "@/utils/supabase/server";
import { redirect } from "next/navigation";
export async function GET(request: Request) {
const supabase = createClient();
await supabase.auth.signOut();
return redirect('/');
}
My old (incorrect) issue: I'm seeing the same issue after following the Supabase Auth + Next.js guide here: https://supabase.com/docs/guides/auth/server-side/nextjs
I have a /logout route that just calls signOut
but none of the cookies are getting removed so the user is effectively never logged out.
import { createClient } from "@/utils/supabase/server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
export default async function Logout() {
const supabase = createClient();
await supabase.auth.signOut();
revalidatePath("/", "layout");
return redirect('/');
}
Navigating to /logout
and the user is not logged out. I have an older app using the Next.js pages router which has effectively the same code as below, and it works correctly so this seems to just be an app router + supabase issue.
Bug report
Describe the bug
I have set up middleware, client and server clients according to Nextjs and Supabase Docs but when i sign out, i still get user and session.
I am using supabase.auth.getSession() on a server component to get session and pass it to a client component. When i click "sign out" , i await supabase.auth.signOut() and then reload the page using window object. I still get to see the session and user objects which should not be the case. I have checked, cookies are CLEARED.
To Reproduce
Fetch Session on a server component. Login using oAuth and then sign out and lastly reload page.
Expected behavior
Session and user Objects should not exist considering that cookies are cleared.
Screenshots
If applicable, add screenshots to help explain your problem.
System information