204 lines
6.2 KiB
Markdown
204 lines
6.2 KiB
Markdown
# Quick Reference: Logout Tracking System
|
||
|
||
## What Was Implemented
|
||
|
||
### 🎯 Goal
|
||
Track **exactly why and where** every user logout happens with precise culprit detection.
|
||
|
||
---
|
||
|
||
## Changes Made
|
||
|
||
### 1. Backend Middleware (`backend/igny8_core/auth/middleware.py`)
|
||
|
||
**Added:**
|
||
- Standardized error codes for all logout reasons
|
||
- Structured JSON responses with logout context
|
||
- Enhanced logging with timestamps and IP addresses
|
||
|
||
**Every logout now returns:**
|
||
```json
|
||
{
|
||
"logout_reason": "SESSION_ACCOUNT_MISMATCH",
|
||
"logout_message": "Session contamination: account ID mismatch",
|
||
"logout_path": "/dashboard/content", // Original page, NOT /signin
|
||
"logout_context": { "stored_account_id": 123, "current_account_id": 456 }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Frontend API Interceptor (`frontend/src/services/api.ts`)
|
||
|
||
**Enhanced:**
|
||
- 401 handler parses backend logout reasons
|
||
- 403 handler detects auth vs permission errors
|
||
- Token refresh failures create detailed logout reasons
|
||
- All logout triggers store reason in localStorage
|
||
- Console logging with 🚨 emoji markers
|
||
|
||
---
|
||
|
||
### 3. Auth Store (`frontend/src/store/authStore.ts`)
|
||
|
||
**Enhanced:**
|
||
- Manual logout captures context before clearing
|
||
- Account/plan validation failures create logout reasons
|
||
- Console logging with 🚪 (manual) and 🚨 (automatic) markers
|
||
|
||
---
|
||
|
||
### 4. SignIn Page (`frontend/src/components/auth/SignInForm.tsx`)
|
||
|
||
**Added:**
|
||
- Yellow alert box showing logout reason
|
||
- Expandable technical details section
|
||
- Console logging of full context
|
||
- Automatic cleanup after display
|
||
|
||
**User sees:**
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ ⚠️ Session Ended │
|
||
│ │
|
||
│ Session contamination: account ID mismatch │
|
||
│ Original page: /dashboard/content │
|
||
│ [ℹ️ Details] │
|
||
└─────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Error Codes
|
||
|
||
### Backend-Triggered
|
||
- `SESSION_ACCOUNT_MISMATCH` - Session contamination
|
||
- `SESSION_USER_MISMATCH` - User ID mismatch
|
||
- `ACCOUNT_MISSING` - No account configured
|
||
- `ACCOUNT_SUSPENDED` - Account suspended
|
||
- `ACCOUNT_CANCELLED` - Account cancelled
|
||
- `PLAN_MISSING` - No plan assigned
|
||
- `PLAN_INACTIVE` - Plan inactive
|
||
|
||
### Frontend-Triggered
|
||
- `TOKEN_REFRESH_FAILED` - Refresh token expired
|
||
- `NO_REFRESH_TOKEN` - Missing refresh token
|
||
- `AUTH_CREDENTIALS_MISSING` - Auth missing (403)
|
||
- `MANUAL_LOGOUT` - User clicked logout
|
||
- `ACCOUNT_REQUIRED` - Account validation failed
|
||
- `PLAN_REQUIRED` - Plan validation failed
|
||
|
||
---
|
||
|
||
## How It Works
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ Logout Happens │
|
||
│ (any reason) │
|
||
└────────┬────────┘
|
||
│
|
||
↓
|
||
┌─────────────────────────────────────────┐
|
||
│ System Creates Logout Reason Object: │
|
||
│ • Error code │
|
||
│ • User-friendly message │
|
||
│ • Original page path (NOT /signin) │
|
||
│ • Debugging context │
|
||
│ • Timestamp │
|
||
│ • Source (backend/frontend) │
|
||
└────────┬────────────────────────────────┘
|
||
│
|
||
├→ Logs to backend (🔍 grep "[AUTO-LOGOUT]")
|
||
├→ Logs to console (🚨 or 🚪 emoji)
|
||
└→ Stores in localStorage
|
||
│
|
||
↓
|
||
┌─────────────────┐
|
||
│ Redirects to │
|
||
│ /signin │
|
||
└────────┬────────┘
|
||
│
|
||
↓
|
||
┌─────────────────────────────────────────┐
|
||
│ SignIn Page Loads: │
|
||
│ 1. Reads logout_reason from localStorage│
|
||
│ 2. Shows yellow alert box to user │
|
||
│ 3. Logs full details to console │
|
||
│ 4. Clears logout_reason │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Debugging
|
||
|
||
### Check Browser Console
|
||
```javascript
|
||
// Look for these log messages:
|
||
🚨 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
|
||
|
||
// Or read stored reason:
|
||
JSON.parse(localStorage.getItem('logout_reason'))
|
||
```
|
||
|
||
### Check Backend Logs
|
||
```bash
|
||
# All auto-logouts
|
||
docker logs igny8_backend 2>&1 | grep "[AUTO-LOGOUT]"
|
||
|
||
# Specific error
|
||
docker logs igny8_backend 2>&1 | grep "SESSION_ACCOUNT_MISMATCH"
|
||
|
||
# Real-time
|
||
docker logs -f igny8_backend | grep "[AUTO-LOGOUT]"
|
||
```
|
||
|
||
---
|
||
|
||
## Key Features
|
||
|
||
✅ **Exact Page Tracking** - Shows where logout happened (not /signin)
|
||
✅ **Detailed Context** - All relevant IDs and state captured
|
||
✅ **User-Friendly Display** - Simple message + expandable details
|
||
✅ **Developer Tools** - Console logs + backend logs + grep-friendly
|
||
✅ **No False Positives** - Only logs out when necessary
|
||
✅ **Automatic Cleanup** - Shown once, then cleared
|
||
|
||
---
|
||
|
||
## Files Modified
|
||
|
||
1. `backend/igny8_core/auth/middleware.py` - Backend logout tracking
|
||
2. `frontend/src/services/api.ts` - API interceptor enhancements
|
||
3. `frontend/src/store/authStore.ts` - Auth store tracking
|
||
4. `frontend/src/components/auth/SignInForm.tsx` - Display component
|
||
|
||
---
|
||
|
||
## Testing
|
||
|
||
```bash
|
||
# 1. Make code change to trigger logout
|
||
# 2. User gets logged out
|
||
# 3. Check console for 🚨 log
|
||
# 4. See yellow alert on signin page
|
||
# 5. Click ℹ️ for technical details
|
||
# 6. Check backend logs for confirmation
|
||
```
|
||
|
||
---
|
||
|
||
## Result
|
||
|
||
**Before:** "Why was I logged out?" 🤷
|
||
**After:** "Session contamination: account ID mismatch on /dashboard/content at 10:30:45" ✅
|
||
|
||
**Every logout is now tracked, explained, and debuggable.**
|