Files
TimeTracker/CSRF_TROUBLESHOOTING.md
Dries Peeters 20824dbcb1 feat: Add customizable Kanban board columns and enhance CSRF configuration
This commit introduces a comprehensive Kanban board customization system and
improves CSRF token configuration for Docker deployments.

## Major Features

### 1. Customizable Kanban Board Columns
Add complete kanban column customization system allowing users to define
custom workflow states beyond the default columns.

**New Components:**
- Add KanbanColumn model with full CRUD operations (app/models/kanban_column.py)
- Add kanban routes blueprint with admin endpoints (app/routes/kanban.py)
- Add kanban column management templates (app/templates/kanban/)
- Add migration 019 for kanban_columns table (migrations/)

**Features:**
- Create unlimited custom columns with unique keys, labels, icons, and colors
- Drag-and-drop column reordering with position persistence
- Toggle column visibility without deletion
- Protected system columns (todo, in_progress, done) prevent accidental deletion
- Complete state marking for columns that should mark tasks as done
- Real-time updates via SocketIO broadcasts when columns change
- Font Awesome icon support (5000+ icons)
- Bootstrap color scheme integration
- Comprehensive validation and error handling

**Integration:**
- Update Task model to work with dynamic column statuses (app/models/task.py)
- Update task routes to use kanban column API (app/routes/tasks.py)
- Update project routes to fetch active columns (app/routes/projects.py)
- Add kanban column management links to base template (app/templates/base.html)
- Update kanban board templates to render dynamic columns (app/templates/tasks/)
- Add cache prevention headers to force fresh column data

**API Endpoints:**
- GET /api/kanban/columns - Fetch all active columns
- POST /api/kanban/columns/reorder - Reorder columns
- GET /kanban/columns - Column management interface (admin only)
- POST /kanban/columns/create - Create new column (admin only)
- POST /kanban/columns/<id>/edit - Edit column (admin only)
- POST /kanban/columns/<id>/delete - Delete column (admin only)
- POST /kanban/columns/<id>/toggle - Toggle column visibility (admin only)

### 2. Enhanced CSRF Configuration
Improve CSRF token configuration and documentation for Docker deployments.

**Configuration Updates:**
- Add WTF_CSRF_ENABLED environment variable to all docker-compose files
- Add WTF_CSRF_TIME_LIMIT environment variable with 1-hour default
- Update app/config.py to read CSRF settings from environment
- Add SECRET_KEY validation in app/__init__.py to prevent production deployment
  with default keys

**Docker Compose Updates:**
- docker-compose.yml: CSRF enabled by default for security testing
- docker-compose.remote.yml: CSRF always enabled in production
- docker-compose.remote-dev.yml: CSRF enabled with production-like settings
- docker-compose.local-test.yml: CSRF can be disabled for local testing
- Add helpful comments explaining each CSRF-related environment variable
- Update env.example with CSRF configuration examples

**Verification Scripts:**
- Add scripts/verify_csrf_config.sh for Unix systems
- Add scripts/verify_csrf_config.bat for Windows systems
- Scripts check SECRET_KEY, CSRF_ENABLED, and CSRF_TIME_LIMIT settings

### 3. Database Initialization Improvements
- Update app/__init__.py to run pending migrations on startup
- Add automatic kanban column initialization after migrations
- Improve error handling and logging during database setup

### 4. Configuration Management
- Update app/config.py with new CSRF and kanban-related settings
- Add environment variable parsing with sensible defaults
- Improve configuration validation and error messages

## Documentation

### New Documentation Files
- CUSTOM_KANBAN_README.md: Quick start guide for kanban customization
- KANBAN_CUSTOMIZATION.md: Detailed technical documentation
- IMPLEMENTATION_SUMMARY.md: Implementation details and architecture
- KANBAN_AUTO_REFRESH_COMPLETE.md: Real-time update system documentation
- KANBAN_REFRESH_FINAL_FIX.md: Cache and refresh troubleshooting
- KANBAN_REFRESH_SOLUTION.md: Technical solution for data freshness
- docs/CSRF_CONFIGURATION.md: Comprehensive CSRF setup guide
- CSRF_DOCKER_CONFIGURATION_SUMMARY.md: Docker-specific CSRF setup
- CSRF_TROUBLESHOOTING.md: Common CSRF issues and solutions
- APPLY_KANBAN_MIGRATION.md: Migration application guide
- APPLY_FIXES_NOW.md: Quick fix reference
- DEBUG_KANBAN_COLUMNS.md: Debugging guide
- DIAGNOSIS_STEPS.md: System diagnosis procedures
- BROWSER_CACHE_FIX.md: Browser cache troubleshooting
- FORCE_NO_CACHE_FIX.md: Cache prevention solutions
- SESSION_CLOSE_ERROR_FIX.md: Session handling fixes
- QUICK_FIX.md: Quick reference for common fixes

### Updated Documentation
- README.md: Add kanban customization feature description
- Update project documentation with new features

## Testing

### New Test Files
- test_kanban_refresh.py: Test kanban column refresh functionality

## Technical Details

**Database Changes:**
- New table: kanban_columns with 11 columns
- Indexes on: key, position
- Default data: 4 system columns (todo, in_progress, review, done)
- Support for both SQLite (development) and PostgreSQL (production)

**Real-Time Updates:**
- SocketIO events: 'kanban_columns_updated' with action type
- Automatic page refresh when columns are created/updated/deleted/reordered
- Prevents stale data by expiring SQLAlchemy caches after changes

**Security:**
- Admin-only access to column management
- CSRF protection on all column mutation endpoints
- API endpoints exempt from CSRF (use JSON and other auth mechanisms)
- System column protection prevents data integrity issues
- Validation prevents deletion of columns with active tasks

**Performance:**
- Efficient querying with position-based ordering
- Cached column data with cache invalidation on changes
- No-cache headers on API responses to prevent stale data
- Optimized database indexes for fast lookups

## Breaking Changes

None. This is a fully backward-compatible addition.

Existing workflows continue to work with the default columns.
Custom columns are opt-in via the admin interface.

## Migration Notes

1. Run migration 019 to create kanban_columns table
2. Default columns are initialized automatically on first run
3. No data migration needed for existing tasks
4. Existing task statuses map to new column keys

## Environment Variables

New environment variables (all optional with defaults):
- WTF_CSRF_ENABLED: Enable/disable CSRF protection (default: true)
- WTF_CSRF_TIME_LIMIT: CSRF token expiration in seconds (default: 3600)
- SECRET_KEY: Required in production, must be cryptographically secure

See env.example for complete configuration reference.

## Deployment Notes
2025-10-11 19:56:45 +02:00

6.5 KiB

CSRF Token Troubleshooting Quick Reference

🔴 Problem: Forms fail with "CSRF token missing or invalid"

Quick Checks (30 seconds)

Run this command to diagnose:

# Linux/Mac
bash scripts/verify_csrf_config.sh

# Windows
scripts\verify_csrf_config.bat

Common Causes & Solutions

1. SECRET_KEY Changed or Not Set

Symptom: All forms suddenly stopped working after restart

Check:

docker-compose exec app env | grep SECRET_KEY

Solution:

# Generate a secure key
python -c "import secrets; print(secrets.token_hex(32))"

# Add to .env file
echo "SECRET_KEY=your-generated-key-here" >> .env

# Restart
docker-compose restart app

Prevention: Store SECRET_KEY in .env file and add to .gitignore


2. CSRF Protection Disabled

Symptom: No csrf_token field in forms

Check:

docker-compose exec app env | grep WTF_CSRF_ENABLED

Solution:

# In .env file
WTF_CSRF_ENABLED=true

# Restart
docker-compose restart app

3. Cookies Blocked by Browser

Symptom: Works on one browser but not another

Check:

  • Open browser DevTools → Application → Cookies
  • Look for session cookie from your domain

Solution:

  • Enable cookies in browser settings
  • Check if browser extensions are blocking cookies
  • Try incognito/private mode to test

4. Reverse Proxy Issues

Symptom: Works on localhost but fails behind nginx/traefik/apache

Check nginx config:

proxy_pass http://timetracker:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# IMPORTANT: Don't strip cookies!
proxy_pass_request_headers on;
proxy_cookie_path / /;

Solution:

  • Ensure proxy forwards cookies
  • Check proxy_cookie_domain and proxy_cookie_path
  • Verify HOST header is correct

5. Token Expired

Symptom: Forms work initially, then fail after some time

Check:

docker-compose exec app env | grep WTF_CSRF_TIME_LIMIT

Solution:

# In .env file - increase timeout (in seconds)
WTF_CSRF_TIME_LIMIT=7200  # 2 hours

# Or disable expiration (less secure)
WTF_CSRF_TIME_LIMIT=null

# Restart
docker-compose restart app

6. Multiple App Instances with Different SECRET_KEYs

Symptom: Intermittent failures, works sometimes but not always

Check:

# Check all containers
docker ps --filter "name=timetracker-app"

# Check each one
docker exec timetracker-app-1 env | grep SECRET_KEY
docker exec timetracker-app-2 env | grep SECRET_KEY

Solution:

  • Ensure ALL instances use the SAME SECRET_KEY
  • Use Docker secrets or environment files
  • Never let each container generate its own key

7. Clock Skew

Symptom: Tokens expire immediately or at wrong times

Check:

docker exec app date
date

Solution:

# On host, sync time
sudo ntpdate -s time.nist.gov

# Or install NTP daemon
sudo apt-get install ntp
sudo systemctl start ntp

# Restart container
docker-compose restart app

8. Development/Testing: Just Disable CSRF

⚠️ WARNING: Only for local development/testing!

# In .env file
WTF_CSRF_ENABLED=false

# Restart
docker-compose restart app

NEVER do this in production!


🔍 Diagnostic Commands

Check Configuration

# View all CSRF-related env vars
docker-compose exec app env | grep -E "(SECRET_KEY|CSRF|COOKIE)"

# Check app logs for CSRF errors
docker-compose logs app | grep -i csrf

# Test health endpoint
curl -v http://localhost:8080/_health

Check Cookies in Browser

  1. Open DevTools (F12)
  2. Go to Application → Cookies
  3. Look for session cookie
  4. Check it has proper domain and path
  5. Verify it's not marked as expired

Verify CSRF Token in HTML

  1. Open any form page
  2. View page source (Ctrl+U)
  3. Search for csrf_token
  4. Should see: <input type="hidden" name="csrf_token" value="...">

Test with curl

# Get login page and save cookies
curl -c cookies.txt http://localhost:8080/login -o login.html

# Extract CSRF token
TOKEN=$(grep csrf_token login.html | grep -oP 'value="\K[^"]+')

# Try to login with token
curl -b cookies.txt -c cookies.txt \
  -d "username=admin" \
  -d "csrf_token=$TOKEN" \
  http://localhost:8080/login

📋 Checklist: Fresh Deployment

When deploying TimeTracker for the first time:

  • Generate secure SECRET_KEY: python -c "import secrets; print(secrets.token_hex(32))"
  • Add SECRET_KEY to .env file
  • Verify WTF_CSRF_ENABLED=true in production
  • If using HTTPS, set SESSION_COOKIE_SECURE=true
  • If behind reverse proxy, configure cookie forwarding
  • Start containers: docker-compose up -d
  • Run verification: bash scripts/verify_csrf_config.sh
  • Test form submission (try logging in)
  • Check logs: docker-compose logs app | grep -i csrf

🆘 Still Not Working?

Enable Debug Logging

# In .env file
LOG_LEVEL=DEBUG

# Restart
docker-compose restart app

# Watch logs
docker-compose logs -f app

Nuclear Option: Fresh Start

# Stop and remove containers
docker-compose down

# Remove volumes (⚠️ this deletes data!)
docker-compose down -v

# Clean rebuild
docker-compose build --no-cache
docker-compose up -d

Get More Help

  1. Check detailed documentation: docs/CSRF_CONFIGURATION.md
  2. Review original fix: CSRF_TOKEN_FIX_SUMMARY.md
  3. Check application logs in logs/timetracker.log
  4. Search existing issues on GitHub
  5. Create new issue with:
    • Output of verify_csrf_config.sh
    • Relevant logs from docker-compose logs app
    • Browser console errors (F12 → Console)
    • Network tab showing failed requests

💡 Pro Tips

  1. Use .env file: Store SECRET_KEY there, never in docker-compose.yml
  2. Version control: Add .env to .gitignore
  3. Documentation: Keep SECRET_KEY in secure password manager
  4. Monitoring: Watch for CSRF errors in logs
  5. Testing: Test after any reverse proxy changes
  6. Backups: Include SECRET_KEY in backup procedures


Last Updated: October 2025
Applies To: TimeTracker v1.0+