# Authentication Setup - Token Persistence ## ✅ Fixed: Token persists across page refreshes ### The Problem After login, refreshing the page redirected to `/login` because the auth state wasn't being restored from the saved token. ### The Solution **No plugin needed!** The token is already saved in localStorage. I updated the router guard to check for the token on page load. --- ## How it works ### 1. **Login Flow** ``` User submits login form ↓ POST /api/auth/login ↓ Backend returns: { success: true, data: { user, token } } ↓ Token saved to localStorage.setItem("auth_token", token) ↓ User saved to Pinia store ↓ Redirect to dashboard ``` ### 2. **Page Refresh Flow** ``` User refreshes page ↓ Router guard runs (beforeEach) ↓ Check: auth.checked? No ↓ Check: localStorage.getItem("auth_token")? Yes ↓ Set auth.token = token (from localStorage) ↓ Fetch user: GET /api/auth/user (with Bearer token) ↓ Backend returns user data ↓ auth.user = userData auth.checked = true ↓ User stays on protected route ``` ### 3. **Logout Flow** ``` User clicks logout ↓ POST /api/auth/logout ↓ localStorage.removeItem("auth_token") ↓ auth.user = null auth.token = null ↓ Redirect to /login ``` --- ## Files Modified ### `src/services/auth.ts` - `login()` saves token to localStorage - `logout()` removes token from localStorage - `me()` fetches user from `/api/auth/user` - `getToken()` retrieves token from localStorage ### `src/services/http.ts` - Automatically adds `Authorization: Bearer {token}` header to all requests - Reads token from localStorage on every request ### `src/stores/auth.ts` - Stores both `user` and `token` in state - `isAuthenticated` checks for both user AND token - `login()` extracts user and token from API response ### `src/router/index.js` - On every navigation, checks if token exists in localStorage - If token exists and auth not checked yet: 1. Sets `auth.token = token` 2. Fetches user data with `auth.fetchMe()` 3. If successful, user stays authenticated 4. If fails (invalid token), clears token and redirects to login ### `src/views/pages/Login.vue` - Form submits to `authStore.login()` - Shows loading state and error messages - Redirects to dashboard on success --- ## API Endpoints Used | Endpoint | Method | Purpose | Auth Required | |----------|--------|---------|---------------| | `/api/auth/login` | POST | Login with email/password | No | | `/api/auth/user` | GET | Get current user | Yes (Bearer token) | | `/api/auth/logout` | POST | Logout | Yes (Bearer token) | --- ## Testing ### Test 1: Fresh Login 1. Go to `/login` 2. Enter credentials: `admin@admin.com` 3. Click "Se connecter" 4. Should redirect to `/dashboards/dashboard-default` 5. Check localStorage: `auth_token` should be present ### Test 2: Page Refresh 1. After login, refresh the page 2. Should stay on dashboard (not redirect to login) 3. Check console: should see "Fetching user from /api/auth/user" ### Test 3: Invalid Token 1. Manually edit token in localStorage to garbage value 2. Refresh page 3. Should clear token and redirect to login 4. Check console: "Invalid token, clearing auth" ### Test 4: Logout 1. After login, click logout 2. Should redirect to `/login` 3. Check localStorage: `auth_token` should be removed --- ## Troubleshooting ### "Still redirects to /login after refresh" - Open browser DevTools → Network tab - Refresh page - Check if `GET /api/auth/user` is called with `Authorization: Bearer ...` header - Check response: - **200 OK**: Token is valid, check if user data is correct format - **401 Unauthorized**: Token is invalid or backend isn't verifying correctly ### "Token is saved but still logged out" - Check `auth.isAuthenticated` in Vue DevTools - Verify both `auth.user` and `auth.token` are set - If only token is set, check if `/api/auth/user` endpoint returns user data ### "Backend doesn't accept token" - Verify backend expects: `Authorization: Bearer {token}` - Check if backend route has auth middleware - Test token manually: `curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8000/api/auth/user` --- ## No Plugin Required! You mentioned Pinia Persisted or Vuex Persisted - you don't need them because: 1. Token is already saved in `localStorage` directly 2. Router guard reads from `localStorage` on app load 3. Token is automatically added to all API requests 4. This is simpler and more explicit than a plugin The only state that needs to persist is the token (string), and we're handling that manually.