supabase / auth-helpers

A collection of framework specific Auth utilities for working with Supabase.

Home Page:https://supabase.github.io/auth-helpers/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cookie not set in Chrome with @supabase/auth-helpers-nextjs

tomelliot opened this issue · comments

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

  • I'm working on a Next.js app that gets built as a static bundle (output: "export" in next.config.js).
  • I'm using the OTP/token auth method (sending an email to the user's email address with a OTP).
  • Because this is a static bundle, there's no server side component (and so there's no setting/receiving cookies from the Next.js backend).
  • I am creating a client by const supabase = createPagesBrowserClient<Database>();
  • Using await supabase.auth.verifyOtp() (from @supabase/auth-helpers-nextjs) I see the user being logged in and the session being set successfully.
  • In Firefox it works as expected.
  • In Chrome:
    • I can see that the response to the /verify request has Set Cookie for both sb-access-token and sb-refresh-token.
    • As soon as the user refreshes the page the session is lost.

In Chrome
the Network response shows both Set Cookie headers:
image

The "Cookies" tab for the request shows only one of the cookies:
image

The Cookies for the localhost domain don't contain either of the sb-... cookies

To Reproduce

I'm working on a minimal reproduction

Expected behavior

Session to persist on both Chrome and Firefox.

Additional context

Chrome version 118.0.5993.96 (Official Build) (arm64)

 npm list | grep supabase
├── @supabase/auth-helpers-nextjs@0.8.7
├── @supabase/supabase-js@2.38.0
├── supabase@1.112.0

Same question on Discord (so far unanswered)

Workaround:

  1. Use the supabase-js createClient instead of @supabase/auth-helpers-nextjs
  2. Use custom storage handlers
import { SupabaseClient, createClient } from '@supabase/supabase-js';
import { deleteCookie, getCookie, setCookie } from 'cookies-next';

supabase:SupabaseClient = createClient<Database>(
    process.env.NEXT_PUBLIC_SUPABASE_URL,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
    {
      auth: {
        storage: {
          getItem(key) {
            return getCookie(key) || null;
          },
          setItem(key, value) {
            return setCookie(key, value, {
              httpOnly: false,
              sameSite: 'none',
              maxAge: Date.now() + 1000 * 60 * 60 * 24 * 365,
              expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365),
              secure: typeof document !== 'undefined' && (document.location?.protocol === 'https' || document.location?.hostname === 'localhost'),
            });
          },
          removeItem(key) {
            return deleteCookie(key, { sameSite: 'none', secure: true });
          },
        },
      },
    },
  );

Note that this is setting sameSite to none which is unsafe.

Modified from #437 (comment)

Thanks for lodging an issue - sorry for the delay in getting back to you!

The auth-helpers and ssr packages are only required to store the session in a cookie making it available serverside. If everything is static with Supabase Auth only being used client-side, using @supabase/supabase-js is the right way to go 👍

You shouldn't need to override the default storage behaviour, as localStorage will be available client-side. This should be fine 👇

import { createClient } from '@supabase/supabase-js';

const supabase = createClient<Database>(
    process.env.NEXT_PUBLIC_SUPABASE_URL,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
  );