diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index a2b2a774..74cef499 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -98,8 +98,15 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) { const currentEmail = session?.user?.email; const newEmailPending = session?.user?.new_email; - setSession(session); - setUser(session?.user ?? null); + // Explicitly handle SIGNED_IN event for iframe compatibility + if (event === 'SIGNED_IN' && session) { + setSession(session); + setUser(session.user); + setLoading(false); + } else { + setSession(session); + setUser(session?.user ?? null); + } // Track pending email changes setPendingEmail(newEmailPending ?? null); diff --git a/src/integrations/supabase/client.ts b/src/integrations/supabase/client.ts index 8da037e4..73e94ccd 100644 --- a/src/integrations/supabase/client.ts +++ b/src/integrations/supabase/client.ts @@ -1,6 +1,7 @@ // This file is automatically generated. Do not edit it directly. import { createClient } from '@supabase/supabase-js'; import type { Database } from './types'; +import { authStorage } from '@/lib/authStorage'; const SUPABASE_URL = "https://ydvtmnrszybqnbcqbdcy.supabase.co"; const SUPABASE_PUBLISHABLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkdnRtbnJzenlicW5iY3FiZGN5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTgzMjYzNTYsImV4cCI6MjA3MzkwMjM1Nn0.DM3oyapd_omP5ZzIlrT0H9qBsiQBxBRgw2tYuqgXKX4"; @@ -10,7 +11,7 @@ const SUPABASE_PUBLISHABLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiO export const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, { auth: { - storage: localStorage, + storage: authStorage, persistSession: true, autoRefreshToken: true, } diff --git a/src/lib/authStorage.ts b/src/lib/authStorage.ts new file mode 100644 index 00000000..42ac5f1c --- /dev/null +++ b/src/lib/authStorage.ts @@ -0,0 +1,58 @@ +/** + * Custom storage adapter for Supabase authentication that handles iframe localStorage restrictions. + * Falls back to sessionStorage or in-memory storage if localStorage is blocked. + */ +class AuthStorage { + private storage: Storage | null = null; + private memoryStorage: Map = new Map(); + private storageType: 'localStorage' | 'sessionStorage' | 'memory' = 'memory'; + + constructor() { + // Try localStorage first + try { + localStorage.setItem('__supabase_test__', 'test'); + localStorage.removeItem('__supabase_test__'); + this.storage = localStorage; + this.storageType = 'localStorage'; + console.log('[AuthStorage] Using localStorage'); + } catch { + // Try sessionStorage as fallback + try { + sessionStorage.setItem('__supabase_test__', 'test'); + sessionStorage.removeItem('__supabase_test__'); + this.storage = sessionStorage; + this.storageType = 'sessionStorage'; + console.log('[AuthStorage] localStorage blocked, using sessionStorage'); + } catch { + // Use in-memory storage as last resort + this.storageType = 'memory'; + console.log('[AuthStorage] Both localStorage and sessionStorage blocked, using in-memory storage'); + } + } + } + + getItem(key: string): string | null { + if (this.storage) { + return this.storage.getItem(key); + } + return this.memoryStorage.get(key) || null; + } + + setItem(key: string, value: string): void { + if (this.storage) { + this.storage.setItem(key, value); + } else { + this.memoryStorage.set(key, value); + } + } + + removeItem(key: string): void { + if (this.storage) { + this.storage.removeItem(key); + } else { + this.memoryStorage.delete(key); + } + } +} + +export const authStorage = new AuthStorage();