Search code examples
javascripttypescriptnext.jsserver-side-renderingsupabase

Cannot log out user on the server side (Next.js and Supabase)


How can I log out a user on the server side when using Supabase as the auth provider?

I thought the simplest and most obvious solution would be to just do that:

export const getServerSideProps: GetServerSideProps = withPageAuth({
    redirectTo: '/auth/sign-in',
    authRequired: true,
    async getServerSideProps(ctx) {
        const session = await supabaseServerClient(ctx).auth.session();
        await supabaseServerClient(ctx).auth.api.signOut(session!.access_token); // There is a valid access token

        return {
            redirect: {
                permanent: false,
                destination: '/auth/sign-in',
            }
        }
    }
});

I believe this is also what the docs say, but when I do that the response from the signOut is:

{ error: null }

But it does not do anything. After the redirects happen the onAuthStateChange on the client side triggers with TOKEN_REFRESH.

There must be something I don't understand, but I don't know what that is.


Solution

  • This will not work because the Supabase Auth Helpers you are using store the tokens inside of cookies for this domain. You will need to also delete the cookies in order for this to work. Alternatively, you should be using the logout endpoint which takes care of all this for you.

    import { supabaseClient, withPageAuth } from "@supabase/auth-helpers-nextjs";
    import {
      setCookies,
      NextRequestAdapter,
      NextResponseAdapter,
    } from "@supabase/auth-helpers-shared";
    
    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,
          },
        };
      },
    });