# Login and Privilege Flow Documentation ## Overview This document describes the complete login flow, including user data fetching, privilege checking, and language synchronization. ## Updated Login Flow (Post-Fix) ### 1. Login Process #### Local Authentication (`useAuth` in `useAuthentication.ts`) ``` User enters credentials → POST /api/local/login → Success ↓ ✅ Tokens stored in httpOnly cookies ✅ authenticationAuthority saved to localStorage ↓ 🔄 IMMEDIATE user data fetch: GET /api/local/me ↓ ✅ User data cached in localStorage ('currentUser') - Includes: username, privilege, language, etc. - Language is part of user data (NO separate storage!) ↓ Navigate to Home page ``` #### Microsoft Authentication (`useMsalAuth` in `useAuthentication.ts`) ``` User clicks Microsoft login → Popup opens → Microsoft OAuth flow ↓ ✅ Tokens stored in httpOnly cookies ✅ authenticationAuthority saved to localStorage ↓ ⏳ Wait 500ms for cookie propagation ↓ 🔄 IMMEDIATE user data fetch: GET /api/msft/me ↓ ✅ User data cached in localStorage ('currentUser') ✅ Language setting synced to localStorage ('language') ↓ Navigate to Home page ``` #### Google Authentication (`useGoogleAuth` in `useAuthentication.ts`) ``` User clicks Google login → Popup opens → Google OAuth flow ↓ ✅ Tokens stored in httpOnly cookies ✅ authenticationAuthority saved to localStorage ↓ ⏳ Wait 500ms for cookie propagation ↓ 🔄 IMMEDIATE user data fetch: GET /api/google/me ↓ ✅ User data cached in localStorage ('currentUser') ✅ Language setting synced to localStorage ('language') ↓ Navigate to Home page ``` ### 2. Home Page Load (`Home.tsx`) ``` Home page mounts ↓ useCurrentUser() hook called ↓ Checks localStorage for cached user data ↓ If cached: Uses cached data (instant) If not cached: Fetches from API (with loading state) ↓ User data available ↓ PageManager receives user data context ``` ### 3. Language Synchronization (`LanguageContext.tsx`) The language context now follows a priority system: **Priority Order:** 1. **User profile language** (from `localStorage('currentUser').language` - synced from backend) 2. **Browser language** (from `navigator.language` - fallback if no user data) **Language Loading:** ``` LanguageProvider mounts ↓ Check currentUser in localStorage ↓ If user.language exists: Use user.language ✅ ↓ Else: Use browser language (fallback) ↓ Load translations for selected language ``` **Language Updates (Settings Flow):** ``` User changes language in settings ↓ 1. Update backend user profile (PUT /api/users/{id}) ↓ 2. Backend returns updated user data ↓ 3. Update localStorage('currentUser') with new data ✅ ↓ 4. Call setLanguage() to load new translations ↓ 5. Trigger 'userInfoUpdated' event ↓ LanguageContext syncs and UI updates ``` ### 4. Privilege Checking System #### Where Privileges Are Checked: **A. Page Level (`PageManager.tsx`)** ```typescript // Line 29-40 in PageManager.tsx const checkPageAccess = async (pageData: GenericPageData): Promise => { if (!pageData.privilegeChecker) { return true; // No checker = accessible to all } try { return await pageData.privilegeChecker(); } catch (error) { console.error(`Error checking page access for ${pageData.path}:`, error); return false; } }; ``` **B. Privilege Checkers (`privilegeCheckers.ts`)** All privilege checkers read from `localStorage.getItem('currentUser')`: ```typescript const getCurrentUserPrivilege = (): string | null => { try { const userData = localStorage.getItem('currentUser'); if (userData) { const user = JSON.parse(userData); return user.privilege || null; } return null; } catch (error) { console.error('Error getting user privilege:', error); return null; } }; ``` **Available Privilege Checkers:** - `privilegeCheckers.adminRole` - For admin and sysadmin users - `privilegeCheckers.sysadminRole` - For sysadmin only - `privilegeCheckers.userRole` - For user, admin, and sysadmin - `privilegeCheckers.viewerRole` - For all authenticated users - `privilegeCheckers.speechSignup` - For speech feature access - `privilegeCheckers.alwaysAllow` - For public pages - `privilegeCheckers.neverAllow` - For disabled features #### Privilege Check Flow: ``` PageManager renders page ↓ checkPageAccess(pageData) ↓ pageData.privilegeChecker() called ↓ Reads from localStorage('currentUser') ↓ Checks user.privilege against required privileges ↓ Returns true/false ↓ If true: Page renders If false: Error component shows ``` ### 5. Complete Flow Diagram ``` ┌─────────────────────────────────────────────────────────────┐ │ LOGIN │ │ (Local/Microsoft/Google) │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ ✅ Set httpOnly cookies (backend) │ │ ✅ Save auth_authority to localStorage │ │ 🔄 IMMEDIATELY fetch user data: GET /api/*/me │ │ ✅ Cache user data in localStorage('currentUser') │ │ ✅ Sync language to localStorage('language') │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ Navigate to Home │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ Home.tsx Mounts │ │ - useCurrentUser() → Reads from localStorage (instant!) │ │ - LanguageProvider → Reads user.language (instant!) │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ PageManager Renders │ │ - Gets currentLanguage from LanguageContext │ │ - Checks page privileges (reads from localStorage) │ │ - Passes language to PageRenderer │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ PageRenderer Displays Page │ │ - Uses user's language for all text │ │ - All privilege checks use cached user data │ └─────────────────────────────────────────────────────────────┘ ``` ## Key Changes Made ### ✅ Fixed Issues: 1. **User data is now fetched IMMEDIATELY after login** - Previously: Fetched only when Home.tsx mounted - Now: Fetched right after successful authentication - Location: `src/hooks/useAuthentication.ts` (lines 65-88 for local, 258-297 for Microsoft, 727-753 for Google) 2. **Language is synced from user profile** - Previously: Loaded from localStorage or browser only - Now: Prioritizes user.language from API response - Location: `src/contexts/LanguageContext.tsx` (lines 42-108) 3. **Language is passed to PageRenderer** - Previously: Default 'de' was used - Now: Current language from context is passed - Location: `src/core/PageManager/PageManager.tsx` (line 104) 4. **Privilege checks use cached user data** - User data is available immediately in localStorage - No race conditions between page load and user data fetch - Location: `src/utils/privilegeCheckers.ts` (lines 4-21) ### 📝 Important Notes: 1. **OAuth Cookie Delay**: Microsoft and Google auth have a 500ms delay before fetching user data to ensure cookies are properly set by the browser. 2. **Error Handling**: If user data fetch fails after login, the user is still navigated to the home page, but will see a loading/error state there. 3. **Cache Strategy**: User data is cached in localStorage for instant access, but is also refreshed on each page load via `useCurrentUser()` hook. 4. **Language Updates**: When a user updates their language in settings, the system: - Updates backend user profile - Triggers 'userInfoUpdated' event - LanguageContext listens and syncs the new language - All components using `useLanguage()` automatically update ## API Endpoints Used | Endpoint | Purpose | When Called | |----------|---------|-------------| | `POST /api/local/login` | Local authentication | User submits login form | | `GET /api/local/me` | Get current user (local) | Immediately after local login + on Home.tsx mount | | `GET /api/msft/me` | Get current user (Microsoft) | Immediately after Microsoft login + on Home.tsx mount | | `GET /api/google/me` | Get current user (Google) | Immediately after Google login + on Home.tsx mount | ## Testing the Flow To verify the flow is working correctly: 1. **Login Test:** ``` - Clear localStorage - Log in with any method - Check console for: "🔄 Fetching user data immediately after login..." - Check console for: "✅ User data fetched and cached" - Verify localStorage has 'currentUser' and 'language' keys ``` 2. **Language Test:** ``` - Log in - Check console for: "🌍 Using language from user data: [language]" - Change language in settings - Verify UI updates immediately ``` 3. **Privilege Test:** ``` - Log in as user with different privilege levels - Navigate to admin pages - Verify access based on privilege - Check console for: "🔍 Checking role privilege" logs ``` ## Troubleshooting ### Issue: Pages show "Access denied" after login **Solution:** Check if user data is properly cached in localStorage. Look for console errors in user data fetch. ### Issue: Wrong language is displayed **Solution:** Verify that user.language exists in the API response. Check browser console for language loading logs. ### Issue: OAuth login doesn't fetch user data **Solution:** Check if the 500ms delay is sufficient for your environment. Increase delay if needed in `useAuthentication.ts`. ## Related Files - `src/hooks/useAuthentication.ts` - Login logic and immediate user fetch - `src/hooks/useUsers.ts` - User data management - `src/contexts/LanguageContext.tsx` - Language management - `src/core/PageManager/PageManager.tsx` - Page routing and privilege checking - `src/core/PageManager/PageRenderer.tsx` - Page rendering with language - `src/utils/privilegeCheckers.ts` - Privilege checking utilities - `src/pages/Home/Home.tsx` - Main application entry after login