Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auth.onAuthStateChanged triggers on tab switch #442

Closed
noty-nick opened this issue May 14, 2022 · 13 comments
Closed

auth.onAuthStateChanged triggers on tab switch #442

noty-nick opened this issue May 14, 2022 · 13 comments
Labels
bug Something isn't working wontfix This will not be worked on

Comments

@noty-nick
Copy link

Bug report

Describe the bug

auth.onAuthStateChanged triggers on tab switch

To Reproduce

  1. Create starter project using this guide https://supabase.com/docs/guides/with-vue-3

  2. add lines to src/main.js

import { supabase } from "./supabase";
supabase.auth.onAuthStateChange(console.log);
  1. run npm run dev
  2. open http://localhost:3000 in browser
  3. open dev console
  4. Switch to another tab
  5. Switch back to previous tab

Expected behavior

1 SIGNED_IN event in console

Actuall behaviour

2 SIGNED_IN event in console

Screenshots

https://www.loom.com/share/56993404e5f348d2bb23b68b0ad15096

System information

  • OS: macOS
  • Browser (if applies) brave
  • Version of supabase-js: 1.35.3
  • Version of Node.js: 16.14.0
@noty-nick noty-nick added the bug Something isn't working label May 14, 2022
@OrangeNote
Copy link

createClient(supabaseUrl, supabaseKey, { ...otherOptions, multiTab: false }) should disable this behavior. I am not sure it's been documented (yet), but I found this option in SupabaseClientOptions and it fixed the issue for me.

@noty-nick
Copy link
Author

@OrangeNote thanks, I will try that

Do you mean this is expected behaviour?

@OrangeNote
Copy link

I'm not sure if it's intentional or if it's an actual issue. I wonder if the object actually changes or if it's always the same after each event. If it stays the same, then I'd say it's a bug or a limitation of some sort when the multiTab option is set.

@noty-nick
Copy link
Author

createClient(supabaseUrl, supabaseKey, { ...otherOptions, multiTab: false }) should disable this behavior. I am not sure it's been documented (yet), but I found this option in SupabaseClientOptions and it fixed the issue for me.

This workaround works for me, I'm closing this issue, as it looks like not a bug, but expected behaviour

@egor-romanov egor-romanov added the wontfix This will not be worked on label Jun 14, 2022
@sjones512
Copy link

It looks like that workaround has been removed.

Any guidance now that the multiTab option is no longer supported?

39b2642

@ian-s-mcb
Copy link

@sjones512 I noticed that that workaround was removed too, but in the release notes for v2 I found a helpful hint.

Deprecated and removed setting for multitab support because getSession() and gotrue’s reuse interval setting takes care of session management across multiple tabs (PR)

In my case, the React user-management quickstart project, I fixed the unwanted XHR to the auth backend by making the following change in src/App.js. I hope it helps you too!

// Before
useEffect(() => {
  supabase.auth.getSession().then(({ data: { session } }) => {
    setSession(session)
  })

  supabase.auth.onAuthStateChange((_event, session) => {
    setSession(session)
  })
}, [])

// After
useEffect(() => {
  supabase.auth.getSession().then(({ data: { session } }) => {
    setSession(session)
  })

  supabase.auth.onAuthStateChange((event, _session) => {
    if (EVENT === 'SIGN_OUT') {
      setSession(null)
    }
  })
}, [])

@madebyfabian
Copy link

Could we reopen this? I think we need another event that is being fired when we change tabs. Because SIGNED_IN, from my perspective, means that a user just has signed in, or got signed in, and not just the session refreshed due to changed tabs.

Maybe it would make sense to have a SIGNED_IN_REFRESH or something, that would be fired.

I am currently handing the SIGNED_IN so that it redirects to the home route of my app, so everytime a user changes between tabs, it'll redirect them, which is not particularly what a user would want.

@rdunk
Copy link

rdunk commented Dec 13, 2022

Possible workaround:

let session = null;

supabase.auth.getSession().then(async ({ data }) => {
  if (data.session) {
    session = data.session;
  }
});

supabase.auth.onAuthStateChange((event, _session) => {
  if (event === 'SIGNED_IN' && !session && _session) {
    // Only triggered on sign in
  }
  session.value = _session;
});

@zakaria-chahboun
Copy link

zakaria-chahboun commented Jan 3, 2023

For SvelteKit users, I did this:

+layout.svelte

let session = null;
onMount(async () => {
    // get the current session
    const {
        data
    } = await supabaseClient.auth.getSession();
    session = data.session;

    // refresh: we did this when user is login with a provider (e.g google)
    if (session && $page.data.session == null) {
        await invalidateAll();
        // location.reload();
    }

    // supabase auth listener
    const {
        data: {
            subscription
        }
    } = supabaseClient.auth.onAuthStateChange((event, new_session) => {
        /*
        	We did this condition cuz of this 'onAuthStateChange' function is triggered
        	Whenever the user changes the browser tab!
        	So - we do not do anything if the session is not changed!
        */
        if (session?.access_token != new_session?.access_token) {
            console.log('session changed');
            session = new_session;

            // reload all routes depends on supabase session
            invalidate('supabase:auth');
            if (event == 'SIGNED_IN') {
                // Do what you want here
            }
        }
    });
    return () => {
        subscription.unsubscribe();
    };
});

@MEAN-James
Copy link

For nuxt users using @nuxtjs/supabase. Seems to be working, thanks @rdunk!

<script lang="ts" setup>
import { useUsers } from "./store/user";
import { Subscription, Session } from "@supabase/gotrue-js";

let authStateSub: Subscription | null = null;
let session: Session | null = null;

onMounted(async () => {
  await useSupabaseClient()
    .auth.getSession()
    .then(({ data }) => {
      if (data.session) {
        session = data.session;
      }
    });

  authStateSub = useSupabaseClient().auth.onAuthStateChange(
    async (event, _session) => {
      console.log(event, session);
      if (!session && _session && event === "SIGNED_IN") {
        console.log("user logged in", _session.user);
        await useUsers().updateOnlineStatus(_session.user.id, true);
        session = _session;
      } else if (session && event === "SIGNED_OUT") {
        console.log("user logged out", session.user);
        await useUsers().updateOnlineStatus(session.user.id, false);
        session = null;
      }
    }
  ).data.subscription;
});

onUnmounted(() => {
  if (authStateSub) {
    authStateSub.unsubscribe();
  }
});

@mijorus
Copy link

mijorus commented Oct 9, 2023

Hi,
not sure if it is related but I want to share my experience with a similar issue.

Basically, I was using the auth.onAuthStateChange callback to make a request to the DB supabase.from('table')....

This resulted in a weird behaviour that was probably causing an internal loop (my guess), as any consequent query was getting stuck.

I just removed the query from the callback

@internpoon
Copy link

For SvelteKit users, I did this:

+layout.svelte

let session = null;
onMount(async () => {
    // get the current session
    const {
        data
    } = await supabaseClient.auth.getSession();
    session = data.session;

    // refresh: we did this when user is login with a provider (e.g google)
    if (session && $page.data.session == null) {
        await invalidateAll();
        // location.reload();
    }

    // supabase auth listener
    const {
        data: {
            subscription
        }
    } = supabaseClient.auth.onAuthStateChange((event, new_session) => {
        /*
        	We did this condition cuz of this 'onAuthStateChange' function is triggered
        	Whenever the user changes the browser tab!
        	So - we do not do anything if the session is not changed!
        */
        if (session?.access_token != new_session?.access_token) {
            console.log('session changed');
            session = new_session;

            // reload all routes depends on supabase session
            invalidate('supabase:auth');
            if (event == 'SIGNED_IN') {
                // Do what you want here
            }
        }
    });
    return () => {
        subscription.unsubscribe();
    };
});

Doesn't work, if I have 2 tabs opened, if i log out on 1 tab, the other tab still can browse protected route.

@PranavvvSingh
Copy link

Hi, not sure if it is related but I want to share my experience with a similar issue.

Basically, I was using the auth.onAuthStateChange callback to make a request to the DB supabase.from('table')....

This resulted in a weird behaviour that was probably causing an internal loop (my guess), as any consequent query was getting stuck.

I just removed the query from the callback

Thanks helped me out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests