2025-10-06 18:38:16 +03:00

168 lines
4.5 KiB
Markdown

# 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.