fix: Resolve login redirect loop and authentication conflicts
- Add delay after login to ensure session cookies are set properly - Fix client-side auth checks in dashboard to handle session refresh gracefully - Remove conflicting client-side redirects from Navigation component - All authentication now properly handled by unified server-side auth system 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -299,13 +299,52 @@ import ThemeToggle from './ThemeToggle.tsx';
|
||||
|
||||
// Check authentication and load user info
|
||||
async function initializeNavigation() {
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
if (!session) {
|
||||
window.location.href = '/';
|
||||
// Try to get session, but don't redirect if none found since auth is handled server-side
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||
|
||||
if (sessionError || !session) {
|
||||
// Try to get user directly (handles token refresh internally)
|
||||
const { data: { user }, error: userError } = await supabase.auth.getUser();
|
||||
|
||||
if (userError || !user) {
|
||||
console.log('[NAV] No user session found, user likely not authenticated');
|
||||
// Don't redirect - let server-side auth handle this
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the user data we got directly
|
||||
const userName = user.user_metadata.name || user.email;
|
||||
const userEmail = user.email;
|
||||
|
||||
// Update all name displays
|
||||
if (userNameText) userNameText.textContent = userName;
|
||||
if (mobileUserNameText) mobileUserNameText.textContent = userName;
|
||||
if (dropdownName) dropdownName.textContent = userName;
|
||||
if (dropdownEmail) dropdownEmail.textContent = userEmail;
|
||||
|
||||
// Generate user initials
|
||||
const initials = userName.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
|
||||
if (userAvatar) userAvatar.textContent = initials;
|
||||
if (mobileUserAvatar) mobileUserAvatar.textContent = initials;
|
||||
if (dropdownAvatar) dropdownAvatar.textContent = initials;
|
||||
|
||||
// Check if user is admin and show admin badge/menu items
|
||||
const { data: userProfile } = await supabase
|
||||
.from('users')
|
||||
.select('role')
|
||||
.eq('id', user.id)
|
||||
.single();
|
||||
|
||||
if (userProfile?.role === 'admin') {
|
||||
if (adminBadge) adminBadge.classList.remove('hidden');
|
||||
if (mobileAdminBadge) mobileAdminBadge.classList.remove('hidden');
|
||||
if (adminMenuItem) adminMenuItem.classList.remove('hidden');
|
||||
if (mobileAdminMenuItem) mobileAdminMenuItem.classList.remove('hidden');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Load user info
|
||||
// Session exists, use session user
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (user) {
|
||||
const userName = user.user_metadata.name || user.email;
|
||||
|
||||
@@ -359,32 +359,46 @@ if (!auth) {
|
||||
async function loadEvents() {
|
||||
try {
|
||||
// Get current user (auth already verified server-side)
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
const { data: { user }, error: userError } = await supabase.auth.getUser();
|
||||
|
||||
if (!user) {
|
||||
// This shouldn't happen due to server-side auth, but handle gracefully
|
||||
console.error('No user found despite server-side auth');
|
||||
loading.innerHTML = `
|
||||
<div class="rounded-xl p-6 max-w-md mx-auto" style="background: var(--error-bg); border: 1px solid var(--error-border);">
|
||||
<p class="font-medium" style="color: var(--error-color);">Session error</p>
|
||||
<p class="text-sm mt-2" style="color: var(--error-color); opacity: 0.8;">Please refresh the page</p>
|
||||
</div>
|
||||
`;
|
||||
if (userError || !user) {
|
||||
// Session might be stale, try to refresh and retry once
|
||||
console.log('[DASHBOARD] No user session found, attempting to refresh...');
|
||||
|
||||
const { data: refreshData, error: refreshError } = await supabase.auth.refreshSession();
|
||||
|
||||
if (refreshError || !refreshData?.user) {
|
||||
// If refresh fails, redirect to login
|
||||
console.error('Session refresh failed, redirecting to login');
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
// Use refreshed user data
|
||||
console.log('[DASHBOARD] Session refreshed successfully for user:', refreshData.user.id);
|
||||
}
|
||||
|
||||
// Get the actual user object (either original or refreshed)
|
||||
const currentUser = user || (await supabase.auth.getUser()).data.user;
|
||||
|
||||
if (!currentUser) {
|
||||
console.error('Unable to get user after refresh attempt');
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: userProfile, error: userError } = await supabase
|
||||
const { data: userProfile, error: userProfileError } = await supabase
|
||||
.from('users')
|
||||
.select('organization_id, role')
|
||||
.eq('id', user.id)
|
||||
.eq('id', currentUser.id)
|
||||
.single();
|
||||
|
||||
if (userError) {
|
||||
if (userProfileError) {
|
||||
// Error loading user profile
|
||||
loading.innerHTML = `
|
||||
<div class="rounded-xl p-6 max-w-md mx-auto" style="background: var(--error-bg); border: 1px solid var(--error-border);">
|
||||
<p class="font-medium" style="color: var(--error-color);">Error loading user profile</p>
|
||||
<p class="text-sm mt-2" style="color: var(--error-color); opacity: 0.8;">${userError.message || userError}</p>
|
||||
<p class="text-sm mt-2" style="color: var(--error-color); opacity: 0.8;">${userProfileError.message || userProfileError}</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
|
||||
@@ -357,13 +357,16 @@ const csrfToken = generateCSRFToken();
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const returnTo = urlParams.get('returnTo') || urlParams.get('redirect');
|
||||
|
||||
// Use the redirectTo from server or fallback to returnTo
|
||||
// Use the redirectTo from server or fallback to returnTo or default dashboard
|
||||
const finalRedirect = returnTo || result.redirectTo || '/dashboard';
|
||||
|
||||
console.log('[LOGIN] Login successful, redirecting to:', finalRedirect);
|
||||
|
||||
// Use window.location.replace to prevent back button issues
|
||||
window.location.replace(finalRedirect);
|
||||
// Small delay to ensure session cookies are set properly
|
||||
setTimeout(() => {
|
||||
// Use window.location.href instead of replace to ensure proper navigation
|
||||
window.location.href = finalRedirect;
|
||||
}, 100);
|
||||
}
|
||||
} catch (error) {
|
||||
errorMessage.textContent = (error as Error).message;
|
||||
|
||||
Reference in New Issue
Block a user