160 lines
5.4 KiB
Markdown
160 lines
5.4 KiB
Markdown
|
|
# Authentication Session Fixes Summary
|
||
|
|
|
||
|
|
## Problem Description
|
||
|
|
|
||
|
|
Users were experiencing frequent logouts (every 5 minutes) and 502 errors when trying to re-login through Keycloak SSO. The authentication system was not properly managing session lifetimes and token refresh.
|
||
|
|
|
||
|
|
## Root Causes Identified
|
||
|
|
|
||
|
|
1. **Short Session Duration**: Cookie lifetime was tied to access token expiry (5 minutes) instead of SSO session duration
|
||
|
|
2. **No Automatic Token Refresh**: Tokens expired without automatic refresh, forcing manual re-login
|
||
|
|
3. **Cookie Domain Issues**: Hardcoded cookie domain causing potential CORS issues
|
||
|
|
4. **Poor Error Handling**: 502 errors weren't handled gracefully with retry logic
|
||
|
|
|
||
|
|
## Solutions Implemented
|
||
|
|
|
||
|
|
### 1. Fixed Session Cookie Duration
|
||
|
|
|
||
|
|
**Files Modified:**
|
||
|
|
- `server/api/auth/keycloak/callback.ts`
|
||
|
|
- `server/api/auth/refresh.ts`
|
||
|
|
- `server/api/auth/session.ts`
|
||
|
|
|
||
|
|
**Changes:**
|
||
|
|
- Changed cookie `maxAge` from access token lifetime (5 minutes) to SSO session duration (8 hours)
|
||
|
|
- Made cookie domain configurable via `COOKIE_DOMAIN` environment variable
|
||
|
|
- Separated access token lifetime from session cookie lifetime
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Before
|
||
|
|
maxAge: tokenResponse.expires_in, // 5 minutes
|
||
|
|
|
||
|
|
// After
|
||
|
|
const sessionDuration = 8 * 60 * 60; // 8 hours in seconds
|
||
|
|
const cookieDomain = process.env.COOKIE_DOMAIN || '.portnimara.dev';
|
||
|
|
maxAge: sessionDuration,
|
||
|
|
domain: cookieDomain,
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Implemented Auto-Refresh System
|
||
|
|
|
||
|
|
**New File:**
|
||
|
|
- `plugins/01.auth-refresh.client.ts`
|
||
|
|
|
||
|
|
**Features:**
|
||
|
|
- Automatically refreshes tokens 2 minutes before expiry
|
||
|
|
- Monitors session expiration client-side
|
||
|
|
- Handles tab visibility changes to refresh when user returns
|
||
|
|
- Graceful fallback to login page on refresh failure
|
||
|
|
|
||
|
|
**Key Functions:**
|
||
|
|
- `scheduleTokenRefresh()`: Schedules automatic token refresh
|
||
|
|
- `checkAndScheduleRefresh()`: Checks current session and schedules refresh
|
||
|
|
- Event listeners for route changes and tab visibility
|
||
|
|
|
||
|
|
### 3. Enhanced Error Handling
|
||
|
|
|
||
|
|
**Files Modified:**
|
||
|
|
- `composables/useCustomAuth.ts`
|
||
|
|
|
||
|
|
**Improvements:**
|
||
|
|
- Added retry logic for network errors (502, 503, etc.)
|
||
|
|
- Better distinction between auth failures (401) and network issues (5xx)
|
||
|
|
- Exponential backoff for retries
|
||
|
|
- Maintains auth state during network issues vs clearing on auth failures
|
||
|
|
|
||
|
|
### 4. Environment Configuration
|
||
|
|
|
||
|
|
**Files Modified:**
|
||
|
|
- `.env.example`
|
||
|
|
|
||
|
|
**New Variables:**
|
||
|
|
```env
|
||
|
|
# Cookie Configuration
|
||
|
|
COOKIE_DOMAIN=.portnimara.dev
|
||
|
|
|
||
|
|
# Keycloak Configuration (used by custom auth)
|
||
|
|
KEYCLOAK_CLIENT_SECRET=your-keycloak-client-secret
|
||
|
|
```
|
||
|
|
|
||
|
|
## Keycloak Admin Console Settings
|
||
|
|
|
||
|
|
These settings were configured in Keycloak to support longer sessions:
|
||
|
|
|
||
|
|
### Realm Settings → Tokens
|
||
|
|
- **SSO Session Idle**: 8 hours
|
||
|
|
- **SSO Session Max**: 12 hours
|
||
|
|
- **Access Token Lifespan**: 5 minutes (kept short for security)
|
||
|
|
- **Client Session Idle**: 8 hours
|
||
|
|
- **Client Session Max**: 12 hours
|
||
|
|
|
||
|
|
### Client Settings
|
||
|
|
- **Use Refresh Tokens**: ON
|
||
|
|
- **Refresh Token Max Reuse**: 0 (unlimited)
|
||
|
|
|
||
|
|
## How It Works Now
|
||
|
|
|
||
|
|
1. **Initial Login**: User authenticates via Keycloak, gets 8-hour session cookie
|
||
|
|
2. **Token Refresh**: Access tokens refreshed automatically every ~3 minutes
|
||
|
|
3. **Session Management**: Session lasts 8 hours or until user explicitly logs out
|
||
|
|
4. **Error Recovery**: Network errors trigger retries; auth errors trigger re-login
|
||
|
|
5. **Tab Management**: Returning to tab triggers session check and refresh if needed
|
||
|
|
|
||
|
|
## Expected Behavior
|
||
|
|
|
||
|
|
- **Users stay logged in**: For up to 8 hours of activity
|
||
|
|
- **No manual re-login**: Unless session truly expires or refresh tokens become invalid
|
||
|
|
- **Graceful error handling**: 502 errors are retried; true auth failures redirect to login
|
||
|
|
- **Background refresh**: Tokens refresh automatically without user interaction
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
### Manual Testing
|
||
|
|
1. Login and monitor console logs for refresh scheduling
|
||
|
|
2. Leave tab open for >5 minutes, verify no logout
|
||
|
|
3. Close/reopen tab, verify automatic session restoration
|
||
|
|
4. Test with network disconnection/reconnection
|
||
|
|
|
||
|
|
### Console Logs to Monitor
|
||
|
|
```
|
||
|
|
[AUTH_REFRESH] Scheduling token refresh in: X ms
|
||
|
|
[AUTH_REFRESH] Attempting automatic token refresh...
|
||
|
|
[AUTH_REFRESH] Token refresh successful, scheduling next refresh
|
||
|
|
[CUSTOM_AUTH] Session check result: { authenticated: true, userId: 'xxx' }
|
||
|
|
```
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Users Still Getting Logged Out
|
||
|
|
1. Check Keycloak realm token settings
|
||
|
|
2. Verify `COOKIE_DOMAIN` environment variable
|
||
|
|
3. Check browser console for refresh errors
|
||
|
|
4. Verify Keycloak client refresh token settings
|
||
|
|
|
||
|
|
### 502 Errors Persist
|
||
|
|
1. Check nginx configuration and upstream health
|
||
|
|
2. Verify network connectivity between services
|
||
|
|
3. Monitor nginx error logs for backend issues
|
||
|
|
4. Check if retry logic is working in browser console
|
||
|
|
|
||
|
|
### Refresh Not Working
|
||
|
|
1. Verify refresh tokens are being issued by Keycloak
|
||
|
|
2. Check client secret configuration
|
||
|
|
3. Monitor network tab for refresh API calls
|
||
|
|
4. Ensure auto-refresh plugin is loading (check console)
|
||
|
|
|
||
|
|
## Security Considerations
|
||
|
|
|
||
|
|
- Access tokens remain short-lived (5 minutes) for security
|
||
|
|
- Refresh tokens enable long sessions without storing access tokens long-term
|
||
|
|
- Session cookies are httpOnly, secure, and sameSite protected
|
||
|
|
- Domain restrictions prevent cross-site cookie access
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
- [ ] Add user notification before session expiry
|
||
|
|
- [ ] Implement sliding session extension on user activity
|
||
|
|
- [ ] Add session management UI for users
|
||
|
|
- [ ] Monitor and alert on high refresh failure rates
|
||
|
|
- [ ] Add metrics for session duration and refresh success rates
|