Possible race condition
Hi!
I have the following structure:
- a login page
- a dashboard page (for signed in users)
- an auth middleware (not global, and both pages are using it via the
definePageMeta)
What's happening:
- I log in using the
signInWithPassword. I await that call, and after it is completed and without errors I redirect the user to the dashboard page. - The auth middleware was triggered, allowed the passage to the dashboard page since for the middleware the session (from
useSupabaseSession) is valid (as expected). - The dashboard page loads. I then have this (more or less, this is a reduced example):
<script setup lang="ts">
const user = useSupabaseUser()
onMounted(async () => {
if (!user.value || !user.value.email) {
console.error("no user!")
}
})
</script>
Problem:
The user is not defined during the onMounted and I don't get why. If I reload the page, it works. If I await a bit before redirecting the page, it also works, but that seems rather inelegant.
Thank you for the help!
If my understanding is correct, this should be handled with a /confirm page (as shown here: https://supabase.nuxtjs.org/getting-started/authentication).
Would it be reasonable to expect that after awaiting signInWithPassword, the client-side useSupabaseUser would already be updated?
If my understanding is correct, this should be handled with a
/confirmpage (as shown here: https://supabase.nuxtjs.org/getting-started/authentication).
This is ideal or using a plugin that listens for an auth state change and triggers an action.
This is mine based off the docs.
// plugins/supabase-auth-listener.client.ts
export default defineNuxtPlugin(() => {
const supa = useSupabaseClient();
const { refreshProfile, logout, doLocalLogout } = useAuth();
const teams = useTeamsStore();
const subKey = '__supabase_auth_sub__';
// Cleanup for HMR
if (import.meta.hot && (window as any)[subKey]?.unsubscribe) {
(window as any)[subKey].unsubscribe();
}
const {
data: { subscription },
} = supa.auth.onAuthStateChange(async (event) => {
switch (event) {
case 'SIGNED_IN':
case 'TOKEN_REFRESHED':
case 'USER_UPDATED': {
await refreshProfile(true);
await teams.initialize(useAuth().profile.value);
break;
}
case 'PASSWORD_RECOVERY':
case 'INITIAL_SESSION': {
await refreshProfile(true);
await teams.initialize(useAuth().profile.value);
break;
}
case 'SIGNED_OUT': {
await doLocalLogout();
break;
}
default:
break;
}
});
(window as any)[subKey] = subscription;
if (import.meta.hot) {
import.meta.hot.dispose(() => subscription.unsubscribe());
}
// Cross-tab sign-outs / sign-ins
window.addEventListener('storage', async (e) => {
if (e.key?.includes('-auth-token')) {
const {
data: { session },
} = await supa.auth.getSession();
if (!session) {
await logout();
} else {
await refreshProfile(true);
await teams.initialize(useAuth().profile.value);
}
}
});
});