# Implementation Guide: Auth Redirect Loop Fix **Date**: 2025-11-18 **Related**: auth-redirect-loop-diagnosis.md **Assignee**: Developer Agent **Priority**: CRITICAL ## Quick Summary Change all authentication cookie references from `"session"` to `"starpunk_session"` to avoid collision with Flask's server-side session mechanism. **Estimated Time**: 30 minutes **Files to Change**: 5 production files + test files ## Root Cause (Brief) Flask's `session` object (used by `flash()` and `session["next"]`) writes to a cookie named `session`. StarPunk's auth also uses a cookie named `session`. This creates a collision where Flask overwrites the auth token, causing the redirect loop. **Solution**: Rename StarPunk's auth cookie to `starpunk_session`. ## Implementation Checklist ### Phase 1: Production Code Changes #### 1. `/home/phil/Projects/starpunk/starpunk/routes/dev_auth.py` **Line 75** - Change cookie name when setting: ```python # OLD (Line 74-81): response.set_cookie( "session", session_token, httponly=True, secure=False, samesite="Lax", max_age=30 * 24 * 60 * 60, ) # NEW: response.set_cookie( "starpunk_session", # ← CHANGED session_token, httponly=True, secure=False, samesite="Lax", max_age=30 * 24 * 60 * 60, ) ``` #### 2. `/home/phil/Projects/starpunk/starpunk/routes/auth.py` **Line 47** - Change cookie read in login form check: ```python # OLD: session_token = request.cookies.get("session") # NEW: session_token = request.cookies.get("starpunk_session") ``` **Line 121** - Change cookie name when setting after IndieAuth callback: ```python # OLD (Lines 120-127): response.set_cookie( "session", session_token, httponly=True, secure=secure, samesite="Lax", max_age=30 * 24 * 60 * 60, ) # NEW: response.set_cookie( "starpunk_session", # ← CHANGED session_token, httponly=True, secure=secure, samesite="Lax", max_age=30 * 24 * 60 * 60, ) ``` **Line 167** - Change cookie read in logout: ```python # OLD: session_token = request.cookies.get("session") # NEW: session_token = request.cookies.get("starpunk_session") ``` **Line 178** - Change cookie delete in logout: ```python # OLD: response.delete_cookie("session") # NEW: response.delete_cookie("starpunk_session") ``` #### 3. `/home/phil/Projects/starpunk/starpunk/auth.py` **Line 390** - Change cookie read in `@require_auth` decorator: ```python # OLD: session_token = request.cookies.get("session") # NEW: session_token = request.cookies.get("starpunk_session") ``` ### Phase 2: Test Code Changes #### 4. `/home/phil/Projects/starpunk/tests/test_routes_admin.py` **Line 54** - Change test cookie name: ```python # OLD: client.set_cookie("session", session_token) # NEW: client.set_cookie("starpunk_session", session_token) ``` #### 5. `/home/phil/Projects/starpunk/tests/test_templates.py` **Lines 234, 247, 259, 272** - Change all test cookie names: ```python # OLD (appears 4 times): client.set_cookie("session", token) # NEW (all 4 instances): client.set_cookie("starpunk_session", token) ``` ### Phase 3: Documentation Updates Update the following documentation files to reflect the new cookie name: 1. `/home/phil/Projects/starpunk/docs/decisions/ADR-011-development-authentication-mechanism.md` (Line 112) 2. `/home/phil/Projects/starpunk/docs/decisions/ADR-005-indielogin-authentication.md` (Line 204) 3. `/home/phil/Projects/starpunk/docs/design/phase-4-quick-reference.md` (Line 460) 4. `/home/phil/Projects/starpunk/docs/design/phase-4-web-interface.md` (Lines 298, 522) 5. `/home/phil/Projects/starpunk/docs/design/phase-3-authentication-implementation.md` (Line 313) **Note**: These are documentation files, so changes are for accuracy but not critical for functionality. ## Complete File Change Summary ### Production Code (5 changes across 3 files) | File | Line | Change Type | Old Value | New Value | |------|------|-------------|-----------|-----------| | `starpunk/routes/dev_auth.py` | 75 | set_cookie name | `"session"` | `"starpunk_session"` | | `starpunk/routes/auth.py` | 47 | cookies.get | `"session"` | `"starpunk_session"` | | `starpunk/routes/auth.py` | 121 | set_cookie name | `"session"` | `"starpunk_session"` | | `starpunk/routes/auth.py` | 167 | cookies.get | `"session"` | `"starpunk_session"` | | `starpunk/routes/auth.py` | 178 | delete_cookie | `"session"` | `"starpunk_session"` | | `starpunk/auth.py` | 390 | cookies.get | `"session"` | `"starpunk_session"` | ### Test Code (5 changes across 2 files) | File | Line(s) | Change Type | |------|---------|-------------| | `tests/test_routes_admin.py` | 54 | client.set_cookie | | `tests/test_templates.py` | 234, 247, 259, 272 | client.set_cookie (4 instances) | ## Search and Replace Strategy **IMPORTANT**: Do NOT use global search and replace. Many documentation files reference the word "session" legitimately. ### Recommended Approach Use targeted search patterns: ```bash # Find all set_cookie calls with "session" grep -n 'set_cookie.*"session"' starpunk/**/*.py tests/**/*.py # Find all cookies.get calls with "session" grep -n 'cookies\.get.*"session"' starpunk/**/*.py tests/**/*.py # Find all delete_cookie calls with "session" grep -n 'delete_cookie.*"session"' starpunk/**/*.py tests/**/*.py ``` Then manually review and update each instance. ## Testing Plan ### Automated Tests After making changes, run the test suite: ```bash uv run pytest tests/ -v ``` **Expected**: All existing tests should pass with the new cookie name. ### Manual Testing (CRITICAL) #### Test 1: Dev Login Flow ``` 1. Start server: uv run flask run 2. Open browser: http://localhost:5000/admin/ 3. Expected: Redirect to /admin/login 4. Click "Dev Login" link (or visit http://localhost:5000/dev/login) 5. Expected: Redirect to /admin/ dashboard 6. Expected: See flash message "DEV MODE: Logged in without authentication" 7. Expected: Dashboard loads successfully (NO redirect loop) ``` **Success Criteria**: - No redirect loop - Flash message appears - Dashboard displays **Browser DevTools Check**: ``` Application → Cookies → http://localhost:5000 Should see: - starpunk_session: {long-token-string} - session: {flask-session-data} (for flash messages) ``` #### Test 2: Session Persistence ``` 1. After successful login from Test 1 2. Click "New Note" in navigation 3. Expected: Form loads (no redirect to login) 4. Refresh page (F5) 5. Expected: Still authenticated, form still loads ``` **Success Criteria**: - No authentication loss on navigation - No authentication loss on refresh #### Test 3: Logout ``` 1. While authenticated, click "Logout" button 2. Expected: Redirect to homepage 3. Expected: Flash message "Logged out successfully" 4. Try to visit http://localhost:5000/admin/ 5. Expected: Redirect to /admin/login ``` **Browser DevTools Check**: ``` Application → Cookies → http://localhost:5000 Should see: - starpunk_session: (should be deleted) - session: {may still exist for flash message} ``` **Success Criteria**: - Cookie properly cleared - Cannot access admin routes after logout - Must login again to access admin #### Test 4: IndieAuth Flow (if configured) ``` 1. Logout if logged in 2. Visit /admin/login 3. Enter valid ADMIN_ME URL 4. Complete IndieAuth flow on indielogin.com 5. Expected: Redirect back to dashboard 6. Expected: starpunk_session cookie set 7. Expected: No redirect loop ``` **Success Criteria**: - Full IndieAuth flow works - Session persists after callback - Flash message shows ## Post-Implementation ### 1. Version Bump Update version to `0.5.1` (bugfix release): ```python # In starpunk/config.py or wherever VERSION is defined app.config["VERSION"] = "0.5.1" ``` Also update in: - `pyproject.toml` (if version is defined there) - `docs/CHANGELOG.md` ### 2. Changelog Entry Add to `/home/phil/Projects/starpunk/docs/CHANGELOG.md`: ```markdown ## [0.5.1] - 2025-11-18 ### Fixed - **CRITICAL**: Fixed authentication redirect loop caused by cookie name collision between Flask's session and StarPunk's auth token - Renamed authentication cookie from `session` to `starpunk_session` to avoid conflict with Flask's server-side session mechanism - All authentication flows (dev login, IndieAuth, logout) now work correctly without redirect loops ### Changed - Authentication cookie name changed from `session` to `starpunk_session` (breaking change for existing sessions - users will need to re-login) ``` ### 3. Update Standards Document Create or update `/home/phil/Projects/starpunk/docs/standards/cookie-naming-convention.md`: ```markdown # Cookie Naming Convention **Status**: ACTIVE **Date**: 2025-11-18 ## Standard All StarPunk application cookies MUST use the `starpunk_` prefix to avoid conflicts with framework-reserved names. ## Reserved Names (DO NOT USE) - `session` - Reserved for Flask server-side session - `csrf_token` - Reserved for CSRF protection frameworks - `remember_token` - Common auth framework name - Any single-word generic names ## StarPunk Cookie Names | Cookie Name | Purpose | Security Attributes | |-------------|---------|---------------------| | `starpunk_session` | Authentication session token | HttpOnly, Secure (prod), SameSite=Lax | ## Future Cookies All future cookies must: 1. Use `starpunk_` prefix 2. Be documented in this table 3. Have explicit security attributes defined 4. Be reviewed for conflicts with framework conventions ``` ### 4. Create Report Create `/home/phil/Projects/starpunk/docs/reports/2025-11-18-auth-redirect-loop-fix.md`: ```markdown # Auth Redirect Loop Fix - Implementation Report **Date**: 2025-11-18 **Version**: 0.5.1 **Severity**: Critical Bug Fix ## Summary Fixed authentication redirect loop in Phase 4 by renaming authentication cookie from `session` to `starpunk_session`. ## Root Cause Cookie name collision between Flask's server-side session (used by flash messages) and StarPunk's authentication token. ## Implementation - Changed 6 instances in production code - Changed 5 instances in test code - Updated 6 documentation files - All tests passing - Manual testing confirmed fix ## Testing - Dev login flow: PASS - Session persistence: PASS - Logout flow: PASS - IndieAuth flow: PASS (if applicable) ## Breaking Change Existing authenticated users will be logged out and need to re-authenticate due to cookie name change. ## Prevention Established cookie naming convention (starpunk_* prefix) to prevent future conflicts. ## Files Changed [List all files modified] ## Commit [Reference commit hash after git commit] ``` ### 5. Git Commit After all changes and testing: ```bash # Stage all changes git add starpunk/routes/dev_auth.py \ starpunk/routes/auth.py \ starpunk/auth.py \ tests/test_routes_admin.py \ tests/test_templates.py \ docs/ # Commit with proper message git commit -m "$(cat <<'EOF' Fix critical auth redirect loop by renaming session cookie BREAKING CHANGE: Authentication cookie renamed from 'session' to 'starpunk_session' Root cause: Cookie name collision between Flask's server-side session (used by flash messages) and StarPunk's authentication token caused redirect loop between /dev/login and /admin/ routes. Changes: - Rename auth cookie to 'starpunk_session' in all routes - Update all cookie read/write operations - Update test suite with new cookie name - Establish cookie naming convention (starpunk_* prefix) - Update documentation to reflect changes Impact: - Existing authenticated users will be logged out - Users must re-authenticate after upgrade Testing: - All automated tests passing - Manual testing confirms fix: - Dev login flow works without redirect loop - Session persistence across requests - Logout properly clears cookie - Flash messages work correctly Fixes: Phase 4 authentication redirect loop Version: 0.5.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude EOF )" ``` ## Verification Checklist Before marking this as complete: - [ ] All 6 production code changes made - [ ] All 5 test code changes made - [ ] Test suite passes: `uv run pytest tests/ -v` - [ ] Manual Test 1 (Dev Login) passes - [ ] Manual Test 2 (Session Persistence) passes - [ ] Manual Test 3 (Logout) passes - [ ] Manual Test 4 (IndieAuth) passes or N/A - [ ] Version bumped to 0.5.1 - [ ] CHANGELOG.md updated - [ ] Cookie naming convention documented - [ ] Implementation report created - [ ] Git commit created with proper message - [ ] No redirect loop observed in any test - [ ] Flash messages still work ## Rollback Plan If issues are discovered: ```bash # Revert the commit git revert HEAD # Or reset if not pushed git reset --hard HEAD~1 ``` The old behavior will be restored, but the redirect loop will return. ## Support If you encounter issues during implementation: 1. Check browser DevTools → Application → Cookies 2. Verify both `starpunk_session` and `session` cookies exist 3. Check Flask logs for session-related errors 4. Verify SECRET_KEY is set in config 5. Ensure all 6 production file changes were made correctly ## Architecture Notes This fix establishes an important principle: **Never use generic cookie names that conflict with framework conventions.** Flask owns the `session` cookie namespace. We must respect framework boundaries and use our own namespace (`starpunk_*`). This is now codified in `/docs/standards/cookie-naming-convention.md` for future reference.