Files
TimeTracker/CSRF_TROUBLESHOOTING.md
Dries Peeters 94e8e49439 feat: Add HTTPS support with mkcert and automatic SSL configuration
Add comprehensive HTTPS support with two deployment options:
- mkcert for local development with trusted certificates
- Automatic SSL with Let's Encrypt for production

HTTPS Implementation:
- Add docker-compose.https-mkcert.yml for local HTTPS development
- Add docker-compose.https-auto.yml for automatic SSL certificates
- Create Dockerfile.mkcert for certificate generation
- Add setup scripts (setup-https-mkcert.sh/bat)
- Add startup scripts (start-https.sh/bat)
- Add certificate generation script (generate-mkcert-certs.sh)

CSRF and IP Access Fixes:
- Fix CSRF token validation for IP-based access
- Add CSRF troubleshooting documentation
- Update configuration to handle various access patterns

Documentation:
- Add HTTPS_MKCERT_GUIDE.md with setup instructions
- Add README_HTTPS.md with general HTTPS documentation
- Add README_HTTPS_AUTO.md for automatic SSL setup
- Add AUTOMATIC_HTTPS_SUMMARY.md
- Add CSRF_IP_ACCESS_FIX.md and CSRF_IP_FIX_SUMMARY.md
- Add docs/CSRF_IP_ACCESS_GUIDE.md
- Update main README.md with HTTPS information

Configuration:
- Update .gitignore for SSL certificates and nginx configs
- Update env.example with new HTTPS-related variables
- Update docker-compose.yml with SSL configuration options

This enables secure HTTPS access in both development and production
environments while maintaining compatibility with existing deployments.
2025-10-13 18:32:45 +02:00

7.2 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. Accessing via IP Address (Not Localhost)

Symptom: Works on localhost but CSRF cookie not created when accessing via IP (e.g., 192.168.1.100)

Cause: WTF_CSRF_SSL_STRICT=true blocks cookies on HTTP connections to non-localhost addresses

Check:

docker-compose exec app env | grep WTF_CSRF_SSL_STRICT

Solution:

# In .env file
WTF_CSRF_SSL_STRICT=false
SESSION_COOKIE_SECURE=false
CSRF_COOKIE_SECURE=false

# Restart
docker-compose restart app

Note: Only use these settings for development/testing on trusted networks. Production should use HTTPS with strict settings.

See: docs/CSRF_IP_ACCESS_GUIDE.md for detailed explanation


9. 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+