auth-helpers icon indicating copy to clipboard operation
auth-helpers copied to clipboard

Next.js - signOut on the server-side does NOT work

Open damian-kociszewski opened this issue 3 years ago • 4 comments

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 }

damian-kociszewski avatar Jul 14 '22 20:07 damian-kociszewski

Please provide more information, there isn't enough information here to reproduce this issue. Do you have an example repo showing this happening?

silentworks avatar Jul 15 '22 12:07 silentworks

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.

silentworks avatar Jul 15 '22 13:07 silentworks

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>

thorwebdev avatar Jul 18 '22 04:07 thorwebdev

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>

This works for sure

ARMATAV avatar Aug 08 '22 21:08 ARMATAV

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 avatar Aug 19 '22 20:08 MattKetmo

@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 avatar Aug 22 '22 11:08 silentworks

@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

MattKetmo avatar Aug 22 '22 12:08 MattKetmo

@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

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 avatar Sep 10 '22 17:09 mikemajara

@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>
  );
}

thorwebdev avatar Sep 11 '22 04:09 thorwebdev