Initial commit: WLED Screen Controller with FastAPI server and Home Assistant integration
Some checks failed
Validate / validate (push) Failing after 1m6s
Some checks failed
Validate / validate (push) Failing after 1m6s
This is a complete WLED ambient lighting controller that captures screen border pixels and sends them to WLED devices for immersive ambient lighting effects. ## Server Features: - FastAPI-based REST API with 17+ endpoints - Real-time screen capture with multi-monitor support - Advanced LED calibration system with visual GUI - API key authentication with labeled tokens - Per-device brightness control (0-100%) - Configurable FPS (1-60), border width, and color correction - Persistent device storage (JSON-based) - Comprehensive Web UI with dark/light themes - Docker support with docker-compose - Windows monitor name detection via WMI (shows "LG ULTRAWIDE" etc.) ## Web UI Features: - Device management (add, configure, remove WLED devices) - Real-time status monitoring with FPS metrics - Settings modal for device configuration - Visual calibration GUI with edge testing - Brightness slider per device - Display selection with friendly monitor names - Token-based authentication with login/logout - Responsive button layout ## Calibration System: - Support for any LED strip layout (clockwise/counterclockwise) - 4 starting position options (corners) - Per-edge LED count configuration - Visual preview with starting position indicator - Test buttons to light up individual edges - Smart LED ordering based on start position and direction ## Home Assistant Integration: - Custom HACS integration - Switch entities for processing control - Sensor entities for status and FPS - Select entities for display selection - Config flow for easy setup - Auto-discovery of devices from server ## Technical Stack: - Python 3.11+ - FastAPI + uvicorn - mss (screen capture) - httpx (async WLED client) - Pydantic (validation) - WMI (Windows monitor detection) - Structlog (logging) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
237
server/docs/AUTHENTICATION.md
Normal file
237
server/docs/AUTHENTICATION.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# API Authentication Guide
|
||||
|
||||
WLED Screen Controller **requires** API key authentication for all API endpoints. This ensures your server is secure and all access is properly authenticated and audited.
|
||||
|
||||
## Configuration
|
||||
|
||||
Authentication is configured in `config/default_config.yaml`. **API keys are mandatory** - the server will not start without at least one configured key.
|
||||
|
||||
### Configure API Keys
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
enabled: true
|
||||
api_keys:
|
||||
home_assistant: "your-secure-api-key-1"
|
||||
web_dashboard: "your-secure-api-key-2"
|
||||
monitoring_script: "your-secure-api-key-3"
|
||||
```
|
||||
|
||||
**Format:** API keys are defined as `label: "key"` pairs where:
|
||||
- **Label**: Identifier for the client (e.g., `home_assistant`, `web_ui`, `admin`)
|
||||
- **Key**: The actual API key (generate strong, random keys)
|
||||
|
||||
**Critical Requirements:**
|
||||
- ⚠️ **At least one API key must be configured** - server will not start without keys
|
||||
- Generate strong, random API keys (use `openssl rand -hex 32`)
|
||||
- Never commit API keys to version control
|
||||
- Use environment variables or secure secret management for production
|
||||
- Each client/service gets its own labeled API key for audit trails
|
||||
- Labels appear in server logs to track which client made requests
|
||||
|
||||
### Server Startup Validation
|
||||
|
||||
If no API keys are configured, the server will fail to start with this error:
|
||||
|
||||
```
|
||||
CRITICAL: No API keys configured!
|
||||
Authentication is REQUIRED for all API requests.
|
||||
Please add API keys to your configuration:
|
||||
1. Generate keys: openssl rand -hex 32
|
||||
2. Add to config/default_config.yaml under auth.api_keys
|
||||
3. Format: label: "your-generated-key"
|
||||
```
|
||||
|
||||
## Using API Keys
|
||||
|
||||
### Web UI
|
||||
|
||||
The web dashboard automatically handles authentication:
|
||||
|
||||
1. When you first load the UI with auth enabled, you'll be prompted for an API key
|
||||
2. Enter your API key - it's stored in browser localStorage
|
||||
3. Click the 🔑 **API Key** button in the header to update or remove the key
|
||||
|
||||
### REST API Clients
|
||||
|
||||
Include the API key in the `Authorization` header:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer your-api-key-here" \
|
||||
http://localhost:8080/api/v1/devices
|
||||
```
|
||||
|
||||
### Home Assistant Integration
|
||||
|
||||
The integration will prompt for an API key during setup if authentication is enabled. You can also configure it in `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
wled_screen_controller:
|
||||
server_url: "http://192.168.1.100:8080"
|
||||
api_key: "your-api-key-here" # Optional, only if auth is enabled
|
||||
```
|
||||
|
||||
### Python Client Example
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
API_KEY = "your-api-key-here"
|
||||
BASE_URL = "http://localhost:8080/api/v1"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {API_KEY}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
# List devices
|
||||
response = requests.get(f"{BASE_URL}/devices", headers=headers)
|
||||
devices = response.json()
|
||||
|
||||
# Start processing
|
||||
response = requests.post(
|
||||
f"{BASE_URL}/devices/device_001/start",
|
||||
headers=headers
|
||||
)
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
### 401 Unauthorized
|
||||
|
||||
**Missing API Key:**
|
||||
```json
|
||||
{
|
||||
"detail": "Missing API key"
|
||||
}
|
||||
```
|
||||
|
||||
**Invalid API Key:**
|
||||
```json
|
||||
{
|
||||
"detail": "Invalid API key"
|
||||
}
|
||||
```
|
||||
|
||||
### 500 Internal Server Error
|
||||
|
||||
**Auth enabled but no keys configured:**
|
||||
```json
|
||||
{
|
||||
"detail": "Server authentication not configured"
|
||||
}
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Public Endpoints (No Auth Required)
|
||||
- `GET /` - Web UI dashboard (static files)
|
||||
- `GET /health` - Health check (for monitoring/health checks)
|
||||
- `GET /docs` - API documentation
|
||||
- `GET /redoc` - Alternative API docs
|
||||
- `/static/*` - Static files (CSS, JS, images)
|
||||
|
||||
### Protected Endpoints (Auth ALWAYS Required)
|
||||
All `/api/v1/*` endpoints **require authentication**:
|
||||
- Device management (`/api/v1/devices/*`)
|
||||
- Processing control (`/api/v1/devices/*/start`, `/api/v1/devices/*/stop`)
|
||||
- Settings and calibration (`/api/v1/devices/*/settings`, `/api/v1/devices/*/calibration`)
|
||||
- Metrics (`/api/v1/devices/*/metrics`)
|
||||
- Display configuration (`/api/v1/config/displays`)
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Development
|
||||
```yaml
|
||||
auth:
|
||||
enabled: false # Disabled for local development
|
||||
```
|
||||
|
||||
### Production
|
||||
```yaml
|
||||
auth:
|
||||
enabled: true
|
||||
api_keys:
|
||||
- "${WLED_API_KEY_1}" # Use environment variables
|
||||
- "${WLED_API_KEY_2}"
|
||||
```
|
||||
|
||||
Set environment variables:
|
||||
```bash
|
||||
export WLED_API_KEY_1="$(openssl rand -hex 32)"
|
||||
export WLED_API_KEY_2="$(openssl rand -hex 32)"
|
||||
```
|
||||
|
||||
### Docker
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
wled-controller:
|
||||
environment:
|
||||
- WLED_AUTH__ENABLED=true
|
||||
- WLED_AUTH__API_KEYS__0=your-key-here
|
||||
```
|
||||
|
||||
Or use Docker secrets for better security.
|
||||
|
||||
## Generating Secure API Keys
|
||||
|
||||
### OpenSSL
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
# Output: 64-character hex string
|
||||
```
|
||||
|
||||
### Python
|
||||
```python
|
||||
import secrets
|
||||
print(secrets.token_hex(32))
|
||||
```
|
||||
|
||||
### Node.js
|
||||
```javascript
|
||||
require('crypto').randomBytes(32).toString('hex')
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
When authentication is enabled, the server logs:
|
||||
- Auth status on startup
|
||||
- Invalid API key attempts (with truncated key for security)
|
||||
- Number of configured keys
|
||||
|
||||
Example startup logs:
|
||||
```
|
||||
INFO: API authentication: ENABLED (2 keys configured)
|
||||
WARNING: Authentication is enabled - API requests require valid API key
|
||||
```
|
||||
|
||||
Invalid attempts:
|
||||
```
|
||||
WARNING: Invalid API key attempt: 1234abcd...
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **HTTPS**: Use HTTPS in production to protect API keys in transit
|
||||
2. **Key Rotation**: Periodically rotate API keys
|
||||
3. **Monitoring**: Monitor logs for invalid key attempts
|
||||
4. **Least Privilege**: Use separate keys for different clients
|
||||
5. **Storage**: Never log or display full API keys
|
||||
6. **Rate Limiting**: Consider adding rate limiting for production (not implemented yet)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Web UI shows "API Key Required" repeatedly
|
||||
- Verify the key is correct
|
||||
- Check browser console for errors
|
||||
- Clear localStorage and re-enter key
|
||||
|
||||
### Home Assistant can't connect
|
||||
- Ensure API key is configured in integration settings
|
||||
- Check server logs for authentication errors
|
||||
- Verify `auth.enabled = true` in server config
|
||||
|
||||
### "Server authentication not configured" error
|
||||
- You enabled auth but didn't add any API keys
|
||||
- Add at least one key to `auth.api_keys` array
|
||||
Reference in New Issue
Block a user