auth-helpers
auth-helpers copied to clipboard
Next.js - signOut on the server-side does NOT work
I created a brand new project with 2 pages:
const MyPage1 = () => {
const signIn = async () => {
await supabaseClient.auth.signIn(
{
provider: "twitch",
},
{
redirectTo: "/",
scopes: process.env.NEXT_PUBLIC_TWITCH_SCOPES,
}
);
}
return (
<div>
<button onClick={signIn}>[Sign in]</button>
</div>
);
};
const MyPage2 = () => {
return (
<div>
MyPage2
</div>
);
};
export const getServerSideProps = withPageAuth({
redirectTo: '/',
async getServerSideProps(ctx) {
await supabaseServerClient(ctx).auth.signOut();
// Note: I have also tried
// const session = supabaseServerClient(ctx).auth.session();
// await supabaseClient.auth.api.signOut(session!.access_token);
// await supabaseServerClient(ctx).auth.api.signOut(session!.access_token);
return {
redirect: {
destination: '/',
permanent: false,
}
};
}
});
I expect the user to be logged out and redirected to '/' after visiting the second page.
The user is redirected but not logged out.
The sign out function returns { error: null }
Please provide more information, there isn't enough information here to reproduce this issue. Do you have an example repo showing this happening?
You need to delete the cookies the auth helper set in order to be fully logged out, so you would need your code to be more like this:
import { supabaseClient, withPageAuth } from "@supabase/auth-helpers-nextjs";
import {
setCookies,
NextRequestAdapter,
NextResponseAdapter,
} from "@supabase/auth-helpers-shared";
export default function About() {
return (
<div>
MyPage2
</div>
);
}
export const getServerSideProps = withPageAuth({
redirectTo: "/",
async getServerSideProps(ctx) {
const session = supabaseClient.auth.session();
await supabaseClient.auth.api.signOut(session.access_token);
setCookies(
new NextRequestAdapter(ctx.req),
new NextResponseAdapter(ctx.res),
["access-token", "refresh-token", "provider-token"].map((key) => ({
name: `sb-${key}`,
value: "",
maxAge: -1,
}))
);
return {
redirect: {
destination: "/",
permanent: false,
},
};
},
});
Maybe we should export a convenient method for logging out programmatically.
The library exports an /api/auth/logout route for logout: https://github.com/supabase-community/auth-helpers/tree/main/packages/nextjs#basic-setup
But yes, needs to be better documented. Usage is like this: https://github.com/supabase-community/auth-helpers/blob/main/examples/nextjs/pages/_app.tsx#L10
<Link href="/api/auth/logout">
<a>Logout</a>
</Link>
The library exports an
/api/auth/logoutroute for logout: https://github.com/supabase-community/auth-helpers/tree/main/packages/nextjs#basic-setupBut yes, needs to be better documented. Usage is like this: https://github.com/supabase-community/auth-helpers/blob/main/examples/nextjs/pages/_app.tsx#L10
<Link href="/api/auth/logout"> <a>Logout</a> </Link>
This works for sure
When using a link to /api/auth/logout the cookies are correctly cleared, but on localStorage there is still a supabase.auth.token item containing all the session info (access token, refresh, user, etc).
The only way I found to clear everything correctly is doing both strategies:
onClick={() => {
supabase.auth.signOut();
router.push("/api/auth/logout");
}}
@MattKetmo this library doesn't make use of localStorage. You might have a another instance of Supabase running in your project that is making use of this.
@silentworks oh my bad, indeed it was because I was not using the client from auth-helpers-nextjs. I started the project without this helper so I missed this:
import { supabaseClient } from '@supabase/auth-helpers-nextjs'
Instead I was creating my own client which by default uses using localStorage with that key:
const supabaseClient = createClient(supabaseUrl, supabaseAnonKey)
...
<UserProvider supabaseClient={supabaseClient}>
After removing my own createClient and importing the one from auth-helpers-nextjs the localStorage item is not there anymore after login 👍
Thanks
@silentworks oh my bad, indeed it was because I was not using the client from auth-helpers-nextjs. I started the project without this helper so I missed this:
import { supabaseClient } from '@supabase/auth-helpers-nextjs'Instead I was creating my own client which by default uses using localStorage with that key:
const supabaseClient = createClient(supabaseUrl, supabaseAnonKey) ... <UserProvider supabaseClient={supabaseClient}>After removing my own createClient and importing the one from
auth-helpers-nextjsthe localStorage item is not there anymore after login 👍Thanks
Can you specify what you imported and where from with a code snippet? I can't find a createClient that can be imported from auth-helpers-nextjs. Do you mean you are using supabaseClient imported from @supabase/auth-helpers-nextjs from every file where you where using import { supabase } from "@lib/auth/supabase-client";?
@mikemajara see the docs: https://github.com/supabase/auth-helpers/blob/main/packages/nextjs/README.md#basic-setup
// pages/_app.js
import React from 'react';
import { UserProvider } from '@supabase/auth-helpers-react';
import { supabaseClient } from '@supabase/auth-helpers-nextjs';
export default function App({ Component, pageProps }) {
return (
<UserProvider supabaseClient={supabaseClient}>
<Component {...pageProps} />
</UserProvider>
);
}