Files
TimeTracker/docs/CSRF_IP_ACCESS_GUIDE.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

286 lines
6.7 KiB
Markdown

# CSRF Cookie Issues with Remote IP Access
## Problem
When accessing the TimeTracker application:
- ✅ Works fine via `http://localhost:8080`
- ❌ CSRF cookie not created when accessing via IP address (e.g., `http://192.168.1.100:8080`)
## Root Cause
The issue occurs due to browser cookie security policies and Flask's CSRF protection settings:
1. **WTF_CSRF_SSL_STRICT**: When set to `true` (default in production), Flask-WTF rejects cookies from non-HTTPS connections that it considers "insecure"
2. **SESSION_COOKIE_SECURE**: When set to `true`, cookies are only sent over HTTPS, blocking HTTP access via IP
3. **SameSite Policy**: Browsers treat localhost and IP addresses differently for cookie SameSite policies
## Quick Fix
### Option 1: Environment Variables (Recommended)
Add these to your `.env` file:
```bash
# Disable SSL strict mode for HTTP access
WTF_CSRF_SSL_STRICT=false
# Ensure cookies work over HTTP
SESSION_COOKIE_SECURE=false
CSRF_COOKIE_SECURE=false
# Optional: Adjust SameSite if needed
SESSION_COOKIE_SAMESITE=Lax
CSRF_COOKIE_SAMESITE=Lax
```
Then restart the application:
```bash
docker-compose restart app
```
### Option 2: Docker Compose Override
Create or update `docker-compose.override.yml`:
```yaml
services:
app:
environment:
- WTF_CSRF_SSL_STRICT=false
- SESSION_COOKIE_SECURE=false
- CSRF_COOKIE_SECURE=false
- SESSION_COOKIE_SAMESITE=Lax
```
Restart:
```bash
docker-compose up -d
```
## Detailed Explanation
### WTF_CSRF_SSL_STRICT
This Flask-WTF setting controls whether CSRF protection rejects requests it considers insecure:
- **`true`** (default in production): Rejects cookies from HTTP on non-localhost addresses
- **`false`**: Allows cookies over HTTP (needed for IP access without HTTPS)
**When to use `false`:**
- Development/testing environments
- Local network access via IP address
- When HTTPS is not configured
**When to use `true`:**
- Production with HTTPS enabled
- Public-facing applications
- Maximum security requirements
### Cookie Secure Flags
**SESSION_COOKIE_SECURE** and **CSRF_COOKIE_SECURE**:
- **`true`**: Cookies only sent over HTTPS (blocks HTTP access)
- **`false`**: Cookies sent over HTTP and HTTPS
### SameSite Policy
Controls when browsers send cookies:
- **`Strict`**: Cookie only sent for same-site requests (most restrictive)
- **`Lax`** (default): Cookie sent for same-site and top-level navigation
- **`None`**: Cookie sent with all requests (requires Secure flag)
## Testing
### 1. Check Current Settings
```bash
docker-compose exec app env | grep -E "(CSRF|SESSION_COOKIE|WTF)"
```
### 2. Verify Cookie Creation
1. Open browser DevTools (F12)
2. Go to **Application****Cookies**
3. Navigate to your app (via IP address)
4. Look for these cookies:
- `session` - Session cookie
- `XSRF-TOKEN` - CSRF token cookie
### 3. Test CSRF Token Endpoint
```bash
# Via localhost (should work)
curl -v http://localhost:8080/auth/csrf-token
# Via IP address (should also work after fix)
curl -v http://192.168.1.100:8080/auth/csrf-token
```
Look for `Set-Cookie` headers in the response.
## Security Considerations
### Development vs Production
**Development (HTTP access via IP):**
```bash
WTF_CSRF_SSL_STRICT=false
SESSION_COOKIE_SECURE=false
CSRF_COOKIE_SECURE=false
```
**Production (HTTPS with domain):**
```bash
WTF_CSRF_SSL_STRICT=true
SESSION_COOKIE_SECURE=true
CSRF_COOKIE_SECURE=true
```
### Risk Assessment
Setting `WTF_CSRF_SSL_STRICT=false`:
-**Safe for**: Local networks, development, testing
- ⚠️ **Risk for**: Public internet without HTTPS
-**Never**: Production with sensitive data over HTTP
### Best Practices
1. **Use HTTPS in Production**: Always enable HTTPS for production deployments
2. **Separate Configs**: Use different settings for dev/prod environments
3. **Network Security**: If using HTTP, ensure network is trusted (VPN, local network)
4. **Monitor Logs**: Watch for CSRF failures in application logs
## Alternative Solutions
### Solution 1: Use a Domain Name
Instead of accessing via IP, use a domain name:
```bash
# Add to /etc/hosts (Linux/Mac) or C:\Windows\System32\drivers\etc\hosts (Windows)
192.168.1.100 timetracker.local
# Access via domain
http://timetracker.local:8080
```
### Solution 2: Enable HTTPS
Set up HTTPS with a self-signed certificate for local development:
```bash
# Generate self-signed certificate
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout key.pem -out cert.pem -days 365 \
-subj "/CN=192.168.1.100"
# Update docker-compose to use HTTPS
# Then set:
WTF_CSRF_SSL_STRICT=true
SESSION_COOKIE_SECURE=true
```
### Solution 3: Disable CSRF (Development Only)
⚠️ **Only for isolated development environments:**
```bash
WTF_CSRF_ENABLED=false
```
**Never use this in production or with real data!**
## Troubleshooting
### Issue: Cookie Still Not Created
**Check 1: Verify environment variables are loaded**
```bash
docker-compose exec app env | grep WTF_CSRF_SSL_STRICT
```
**Check 2: Restart the container**
```bash
docker-compose restart app
```
**Check 3: Check application logs**
```bash
docker-compose logs app | tail -50
```
### Issue: CSRF Token Works but Form Fails
This is different from cookie creation. Check:
1. Token in HTML form: View page source and search for `csrf_token`
2. Token in request: Browser DevTools → Network → Form Data
3. Token expiration: Increase `WTF_CSRF_TIME_LIMIT`
### Issue: Works on Chrome but not Firefox/Safari
Different browsers have different cookie policies:
1. Try disabling enhanced tracking protection
2. Check browser console for cookie warnings
3. Use consistent SameSite settings
## Configuration Examples
### Local Development (HTTP, IP Access)
```bash
# .env
FLASK_ENV=development
WTF_CSRF_ENABLED=true
WTF_CSRF_SSL_STRICT=false
SESSION_COOKIE_SECURE=false
CSRF_COOKIE_SECURE=false
SESSION_COOKIE_SAMESITE=Lax
CSRF_COOKIE_SAMESITE=Lax
```
### Production (HTTPS, Domain)
```bash
# .env
FLASK_ENV=production
WTF_CSRF_ENABLED=true
WTF_CSRF_SSL_STRICT=true
SESSION_COOKIE_SECURE=true
CSRF_COOKIE_SECURE=true
SESSION_COOKIE_SAMESITE=Strict
CSRF_COOKIE_SAMESITE=Strict
```
### Testing (Disable CSRF)
```bash
# .env (isolated test environment only!)
FLASK_ENV=development
WTF_CSRF_ENABLED=false
```
## Related Documentation
- [CSRF Configuration Guide](CSRF_CONFIGURATION.md)
- [CSRF Troubleshooting](../CSRF_TROUBLESHOOTING.md)
- [Docker Setup Guide](DOCKER_PUBLIC_SETUP.md)
## Summary
**The core issue**: `WTF_CSRF_SSL_STRICT=true` (default) blocks cookie creation for HTTP access via IP addresses.
**The solution**: Set `WTF_CSRF_SSL_STRICT=false` when accessing via IP without HTTPS.
**For production**: Always use HTTPS with proper domain names and keep strict settings enabled.
---
**Last Updated:** October 2024
**Applies To:** TimeTracker v1.0+