diff --git a/src/context/AuthContext.jsx b/src/context/AuthContext.jsx index 51bd1d4..a45d7ee 100644 --- a/src/context/AuthContext.jsx +++ b/src/context/AuthContext.jsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useEffect, useState } from "react"; +import React, { createContext, useContext, useEffect, useRef, useState } from "react"; import { demoUsers } from "../data/mockAppData"; import { supabase, hasSupabaseConfig } from "../supabaseClient"; @@ -130,9 +130,9 @@ const clearAllAuthStorage = () => { }; export const AuthProvider = ({ children }) => { + // Supabase mode: always start null, session restore via onAuthStateChange + // Demo mode: restore from localStorage const [user, setUser] = useState(() => { - // Demo mode reads from localStorage; Supabase mode always starts null - // (session restore happens via onAuthStateChange/getSession) if (hasSupabaseConfig) return null; const stored = localStorage.getItem(STORAGE_KEY); return stored ? decodeLocalAuth(stored) : null; @@ -142,6 +142,9 @@ export const AuthProvider = ({ children }) => { const [isLoading, setIsLoading] = useState(false); const [authError, setAuthError] = useState(""); + // Ref to prevent getSession from restoring session after explicit signOut + const signedOutRef = useRef(false); + useEffect(() => { if (!hasSupabaseConfig || !supabase) { return undefined; @@ -156,6 +159,11 @@ export const AuthProvider = ({ children }) => { return; } + // If user explicitly signed out, don't auto-restore session + if (signedOutRef.current) { + return; + } + const baseUser = mapSessionUserToAuthUser(session.user); if (baseUser) { fetchUserProfile(session.user.id).then((profile) => { @@ -180,6 +188,11 @@ export const AuthProvider = ({ children }) => { return; } + // Don't restore session if user explicitly signed out + if (signedOutRef.current) { + return; + } + if (data.session?.user) { const baseUser = mapSessionUserToAuthUser(data.session.user); if (baseUser) { @@ -266,6 +279,9 @@ export const AuthProvider = ({ children }) => { throw normalizeOtpError(new Error(edgeErrorMessage || (error instanceof Error ? error.message : String(error)) || PROFILE_LOAD_ERROR)); } + // Clear signedOut flag — user is logging in + signedOutRef.current = false; + if (data?.session?.access_token && data?.session?.refresh_token) { const { data: sessionData, error: sessionError } = await supabase.auth.setSession({ access_token: data.session.access_token, @@ -277,14 +293,14 @@ export const AuthProvider = ({ children }) => { } const baseUser = mapSessionUserToAuthUser(sessionData.session?.user || data.session.user); - if (baseUser) { - const profile = await fetchUserProfile(baseUser.id); - if (profile) { - setUser(mapProfileToAuthUser(profile)); - } else { - setUser({ ...baseUser, role: baseUser.role || "manager" }); + if (baseUser) { + const profile = await fetchUserProfile(baseUser.id); + if (profile) { + setUser(mapProfileToAuthUser(profile)); + } else { + setUser({ ...baseUser, role: baseUser.role || "manager" }); + } } - } } else { setUser(mapSessionUserToAuthUser(data?.user || null)); } @@ -310,11 +326,20 @@ export const AuthProvider = ({ children }) => { }; const signOut = async () => { + // Set flag BEFORE signOut to prevent onAuthStateChange/getSession from restoring session + signedOutRef.current = true; + if (hasSupabaseConfig && supabase) { - await supabase.auth.signOut({ scope: "local" }); + try { + await supabase.auth.signOut({ scope: "local" }); + } catch (e) { + // Ignore — session may already be invalid + } } - // Hard clear all auth storage so auto-login is impossible after logout + + // Hard clear all auth storage so auto-login is impossible clearAllAuthStorage(); + setUser(null); setPendingEmail(""); setIsOtpSent(false);