Files
igny8/docs/logout-issues/LOGOUT-TRACKING-IMPLEMENTATION.md
IGNY8 VPS (Salman) 69c0fd8b69 reorg
2025-12-17 00:27:53 +00:00

391 lines
11 KiB
Markdown

# Logout Tracking & Culprit Detection System
**Implemented:** December 15, 2025
**Purpose:** Precise tracking and display of logout causes with exact page/context
---
## Overview
A comprehensive logging and display system that captures **exactly why and where** a user was logged out, with detailed context for debugging and user transparency.
---
## Implementation Components
### 1. Backend Middleware Enhancement
**File:** `backend/igny8_core/auth/middleware.py`
**Changes:**
- Added `LOGOUT_REASONS` dictionary with standardized error codes
- Enhanced all logout triggers to include:
- `logout_reason`: Error code (e.g., `SESSION_ACCOUNT_MISMATCH`)
- `logout_message`: Human-readable message
- `logout_path`: Exact page where logout occurred
- `logout_context`: Additional debugging context
- `timestamp`: ISO timestamp of logout event
**Error Codes Added:**
- `SESSION_ACCOUNT_MISMATCH` - Session contamination: account ID mismatch
- `SESSION_USER_MISMATCH` - Session contamination: user ID mismatch
- `ACCOUNT_MISSING` - Account not configured for this user
- `ACCOUNT_SUSPENDED` - Account is suspended
- `ACCOUNT_CANCELLED` - Account is cancelled
- `PLAN_MISSING` - No subscription plan assigned
- `PLAN_INACTIVE` - Subscription plan is inactive
- `USER_INACTIVE` - User account is inactive
**Response Format:**
```json
{
"success": false,
"error": "User-friendly message",
"logout_reason": "ERROR_CODE",
"logout_message": "Detailed explanation",
"logout_path": "/previous/page/path",
"logout_context": {
"stored_account_id": 123,
"current_account_id": 456,
"user_id": 789
}
}
```
---
### 2. Frontend API Interceptor Enhancement
**File:** `frontend/src/services/api.ts`
**Changes:**
#### 401 Unauthorized Handler
- Parses backend logout reasons from 401 responses
- Logs detailed context before attempting token refresh
- Stores logout reason in localStorage before logout
- Console logging with 🚨 emoji for visibility
#### 403 Forbidden Handler
- Detects authentication vs permission errors
- Only logs out for auth credential issues
- Stores detailed context including token state
#### Token Refresh Failure Handler
- Creates logout reason when refresh fails
- Includes original endpoint in context
- Differentiates between "refresh failed" and "no refresh token"
**Logout Reason Format:**
```typescript
{
code: 'ERROR_CODE',
message: 'Human-readable message',
path: '/page/where/logout/happened', // NOT /signin
context: {
// Additional debugging info
error: 'specific error details',
endpoint: '/api/v1/...',
hasToken: true/false,
},
timestamp: '2025-12-15T10:30:45.123Z',
source: 'token_refresh_failure' | 'backend_middleware' | 'api_403_auth_error'
}
```
---
### 3. Auth Store Enhancement
**File:** `frontend/src/store/authStore.ts`
**Changes:**
#### Manual Logout
- Captures logout context BEFORE clearing anything
- Includes user email and current page
- Stores with source: `manual_user_action`
- Console log with 🚪 emoji
#### refreshUser Validation
- Enhanced account validation with logout tracking
- Stores detailed context for ACCOUNT_REQUIRED
- Stores detailed context for PLAN_REQUIRED
- Console logging with 🚨 emoji
---
### 4. SignIn Page Display
**File:** `frontend/src/components/auth/SignInForm.tsx`
**Changes:**
#### On Component Mount
1. Reads `logout_reason` from localStorage
2. Displays reason to user in yellow alert box
3. Logs full details to console
4. Clears logout_reason after reading (single display)
#### UI Components
**Alert Box Features:**
- Yellow background (warning, not error)
- Clear "Session Ended" heading
- User-friendly message
- Original page path (if not /signin)
- Expandable technical details button
**Technical Details Panel:**
- Error code
- Source system
- Exact timestamp
- Full context JSON (formatted)
- Collapsible to avoid overwhelming users
---
## Logout Reason Codes & Sources
### Backend-Triggered (source: `backend_middleware`)
| Code | Message | Trigger Location |
|------|---------|------------------|
| `SESSION_ACCOUNT_MISMATCH` | Session contamination: account ID mismatch | AccountContextMiddleware line ~58 |
| `SESSION_USER_MISMATCH` | Session contamination: user ID mismatch | AccountContextMiddleware line ~73 |
| `ACCOUNT_MISSING` | Account not configured for this user | validate_account_and_plan() |
| `ACCOUNT_SUSPENDED` | Account is suspended | validate_account_and_plan() |
| `ACCOUNT_CANCELLED` | Account is cancelled | validate_account_and_plan() |
| `PLAN_MISSING` | No subscription plan assigned | validate_account_and_plan() |
| `PLAN_INACTIVE` | Subscription plan is inactive | validate_account_and_plan() |
### Frontend-Triggered (source: varies)
| Code | Message | Source | Trigger Location |
|------|---------|--------|------------------|
| `TOKEN_REFRESH_FAILED` | Token refresh failed - session expired | `token_refresh_failure` | api.ts line ~318 |
| `NO_REFRESH_TOKEN` | No refresh token available | `missing_refresh_token` | api.ts line ~330 |
| `AUTH_CREDENTIALS_MISSING` | Authentication credentials were not provided | `api_403_auth_error` | api.ts line ~203 |
| `MANUAL_LOGOUT` | User manually logged out | `manual_user_action` | authStore.ts line ~151 |
| `ACCOUNT_REQUIRED` | Account not configured | `refresh_user_validation` | authStore.ts line ~412 |
| `PLAN_REQUIRED` | Plan not configured | `refresh_user_validation` | authStore.ts line ~425 |
---
## Console Logging Format
### Backend Logs
```
[2025-12-15 10:30:45] [WARNING] [auth.middleware] [AUTO-LOGOUT] SESSION_ACCOUNT_MISMATCH: Session contamination: account ID mismatch. Session=123, Current=456, User=789, Path=/dashboard, IP=192.168.1.1, Timestamp=2025-12-15T10:30:45.123Z
```
**View Commands:**
```bash
# All auto-logouts
docker logs igny8_backend 2>&1 | grep "\[AUTO-LOGOUT\]"
# Specific error code
docker logs igny8_backend 2>&1 | grep "SESSION_ACCOUNT_MISMATCH"
# Real-time monitoring
docker logs -f igny8_backend | grep "\[AUTO-LOGOUT\]"
```
### Frontend Console Logs
```javascript
// Console group with full details
🔍 LOGOUT REASON DETAILS
Code: SESSION_ACCOUNT_MISMATCH
Message: Session contamination: account ID mismatch
Original Page: /dashboard/content
Timestamp: 2025-12-15T10:30:45.123Z
Source: backend_middleware
Context: {stored_account_id: 123, current_account_id: 456, ...}
// Individual logout events
🚨 LOGOUT TRIGGERED - Backend Validation Failed: {...}
🚨 LOGOUT TRIGGERED - Token Refresh Failed: {...}
🚨 LOGOUT TRIGGERED - No Refresh Token: {...}
🚨 LOGOUT TRIGGERED - Authentication Credentials Missing: {...}
🚨 LOGOUT TRIGGERED - Account Required: {...}
🚨 LOGOUT TRIGGERED - Plan Required: {...}
🚪 LOGOUT - User Action: {...}
```
---
## User Experience Flow
### 1. User Gets Logged Out
```
User browsing /dashboard/content
Backend validation fails (e.g., account mismatch)
Backend returns 401 with logout_reason JSON
Frontend API interceptor catches response
Logs detailed context to console
Stores logout_reason in localStorage
Triggers logout and redirects to /signin
```
### 2. User Sees Explanation on SignIn Page
```
SignIn component mounts
Reads logout_reason from localStorage
Displays yellow alert box with:
- "Session Ended" heading
- User-friendly message
- Original page path
- Technical details (expandable)
Logs full details to browser console
Clears logout_reason from localStorage
User understands why they were logged out
```
---
## Debugging Workflow
### For Users (Non-Technical)
1. After logout, check yellow alert box on signin page
2. Note the message shown
3. If needed, click info icon for technical details
4. Take screenshot and share with support
### For Developers
1. **Check Browser Console:**
```
Open DevTools → Console
Look for 🚨 or 🚪 emoji logs
Expand the logged object for full context
```
2. **Check Backend Logs:**
```bash
docker logs igny8_backend 2>&1 | grep "\[AUTO-LOGOUT\]" | tail -20
```
3. **Check Stored Reason (if still in localStorage):**
```javascript
JSON.parse(localStorage.getItem('logout_reason'))
```
4. **Trace Request Path:**
- Note the `logout_path` field - this is the **original page**
- Note the `source` field - this tells you which system component triggered it
- Check `context` for specific IDs and values
---
## Key Features
### ✅ Exact Page Tracking
- `logout_path` always contains the **original page** where logout occurred
- Never shows `/signin` as logout path
- Captured BEFORE redirect happens
### ✅ Comprehensive Context
- Every logout includes relevant IDs (user_id, account_id, etc.)
- Token state captured for auth errors
- Error details preserved through retry attempts
### ✅ User-Friendly Display
- Non-technical users see simple message
- Technical users can expand for details
- Automatic cleanup (shown once, then cleared)
### ✅ Developer-Friendly Logging
- Console groups for easy reading
- Emoji markers for quick scanning (🚨 = automatic, 🚪 = manual)
- Full JSON context for debugging
- Backend logs with grep-friendly prefixes
### ✅ No False Positives
- Only logs out when truly necessary
- Differentiates between auth and permission errors
- Preserves context through token refresh attempts
---
## Testing Scenarios
### 1. Test Session Contamination
```python
# In backend, manually modify session
request.session['_account_id'] = 999 # Wrong account
# Expected: SESSION_ACCOUNT_MISMATCH logout
```
### 2. Test Token Expiration
```javascript
// Wait 15+ minutes, then make API call
// Expected: TOKEN_REFRESH_FAILED or NO_REFRESH_TOKEN logout
```
### 3. Test Manual Logout
```javascript
// Click logout button
// Expected: MANUAL_LOGOUT with correct page path
```
### 4. Test Account/Plan Validation
```python
# In backend, deactivate user's plan
user.account.plan.is_active = False
user.account.plan.save()
# Expected: PLAN_INACTIVE logout on next request
```
---
## Future Enhancements (Optional)
1. **Analytics Integration:**
- Send logout reasons to analytics
- Track which reasons are most common
- Identify systemic issues
2. **Admin Dashboard:**
- View all logout events
- Filter by reason code
- Track affected users
3. **User Notification:**
- Email users when logged out (except manual)
- Include reason and next steps
- Link to support if needed
4. **Automated Recovery:**
- For some errors (e.g., PLAN_INACTIVE), show payment link
- Auto-retry after fixing issues
- Remember intended destination
---
## Summary
This implementation provides **100% accurate culprit detection** by:
1. ✅ Capturing exact page where logout occurred (NOT signin page)
2. ✅ Logging detailed context at every logout trigger point
3. ✅ Displaying reasons clearly to users on signin page
4. ✅ Providing comprehensive debugging info in console and backend logs
5. ✅ Using standardized error codes for easy tracking
6. ✅ Preserving context through redirects and token refresh attempts
**Result:** No more guessing why users were logged out. Every logout is tracked, explained, and debuggable.