mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
fix: use getSession() in useAuth hook (fixes 10s timeout)
PR #5 switched client components to getSession() but missed src/hooks/use-auth.ts. The auth hook was still calling supabase.auth.getUser() which makes a network round-trip to Supabase, and on some deployments the request was hanging long enough to trigger the 10-second safety timeout: [browser] [useAuth] getUser() timed out after 10s, clearing loading state This caused the dashboard to sit on the loading spinner for the full 10 seconds on every page load. Changes: - Replaced getUser() with getSession() in init() — reads from localStorage synchronously (no network). - Reduced safety timer from 10s to 3s. getSession() shouldn't take more than a few hundred ms; 3s is a reasonable ceiling. Security note (same reasoning as PR #5): - The middleware server-side STILL uses getUser() to verify the JWT against Supabase on every request, so unauthenticated users can't reach protected routes. - RLS on the database is the actual authorization boundary. - getSession() on the client is only used to decide what UI to render. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aaaddf0d5a
commit
8f0f8afae3
@ -20,13 +20,14 @@ export function useAuth() {
|
|||||||
const supabase = createClient();
|
const supabase = createClient();
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
|
||||||
// Safety net: if something hangs, surface it instead of an infinite spinner.
|
// Safety net: 3s is plenty for localStorage reads. If it hangs here,
|
||||||
|
// something else is wrong (likely storage permissions in an iframe).
|
||||||
const safetyTimer = setTimeout(() => {
|
const safetyTimer = setTimeout(() => {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
console.warn("[useAuth] getUser() timed out after 10s, clearing loading state");
|
console.warn("[useAuth] getSession() timed out after 3s, clearing loading state");
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, 10000);
|
}, 3000);
|
||||||
|
|
||||||
const fetchProfile = async (userId: string) => {
|
const fetchProfile = async (userId: string) => {
|
||||||
try {
|
try {
|
||||||
@ -57,23 +58,25 @@ export function useAuth() {
|
|||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
try {
|
try {
|
||||||
|
// getSession() reads from localStorage — instant, no network call.
|
||||||
|
// The middleware already validates the JWT server-side with getUser()
|
||||||
|
// on every request, and RLS enforces authorization at the DB level,
|
||||||
|
// so the client can trust the local session for UI purposes.
|
||||||
const {
|
const {
|
||||||
data: { user },
|
data: { session },
|
||||||
error,
|
error,
|
||||||
} = await supabase.auth.getUser();
|
} = await supabase.auth.getSession();
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
// AuthSessionMissingError is expected when not logged in — don't log as error
|
console.error("[useAuth] getSession error:", error.message);
|
||||||
if (error.name !== "AuthSessionMissingError") {
|
|
||||||
console.error("[useAuth] getUser error:", error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setUser(user);
|
const currentUser = session?.user ?? null;
|
||||||
|
setUser(currentUser);
|
||||||
|
|
||||||
if (user) {
|
if (currentUser) {
|
||||||
await fetchProfile(user.id);
|
await fetchProfile(currentUser.id);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[useAuth] init threw:", err);
|
console.error("[useAuth] init threw:", err);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user