🔒 security(auth): migrate to EdDSA JWT and add automated monitoring

BREAKING: JWT keys are now auto-managed by Better Auth (EdDSA/Ed25519)
- Remove all JWT_PRIVATE_KEY, JWT_PUBLIC_KEY, JWT_SECRET references
- Keys stored in auth.jwks database table (auto-generated on first run)
- Delete obsolete generate-keys.sh and generate-staging-secrets.sh scripts
- Clean up legacy AUTH_*.md analysis files from root

Security Improvements:
- Add security_events table for audit logging
- Add SecurityEventsService for tracking auth events
- Enhanced security headers (HSTS, CSP, X-Frame-Options)
- Rate limiting configuration

Monitoring Setup:
- Add auth-health-check.sh for automated testing
- Add generate-dashboard.sh for HTML status dashboard
- Tests: health endpoint, JWKS (EdDSA), security headers, response time
- Ready for Hetzner cron deployment

Documentation:
- Update deployment docs with Better Auth notes
- Update environment variable references
- Add security improvements documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Wuesteon 2025-12-18 21:42:47 +01:00
parent 1214c78a3c
commit 4d15d9e764
56 changed files with 6870 additions and 4154 deletions

View file

@ -108,38 +108,16 @@ STAGING_AZURE_OPENAI_API_KEY=<your-api-key>
STAGING_AZURE_OPENAI_API_VERSION=2024-12-01-preview
```
#### JWT Configuration (Staging)
#### JWT Configuration
Generate JWT keys:
```bash
# Generate private key
openssl genrsa -out jwt-private.pem 2048
# Extract public key
openssl rsa -in jwt-private.pem -pubout -out jwt-public.pem
# Generate secret
openssl rand -hex 32
# View private key (copy to STAGING_JWT_PRIVATE_KEY)
cat jwt-private.pem
# View public key (copy to STAGING_JWT_PUBLIC_KEY)
cat jwt-public.pem
```
Add to GitHub:
```
STAGING_JWT_SECRET=<hex-secret>
STAGING_JWT_PUBLIC_KEY=<public-key-content>
STAGING_JWT_PRIVATE_KEY=<private-key-content>
```
**Note:** JWT keys are managed automatically by Better Auth (EdDSA/Ed25519).
Keys are auto-generated on first startup and stored in the `auth.jwks` database table.
No manual key generation or configuration is required.
#### Production Secrets
Repeat all the above for production with `PRODUCTION_` prefix.
**Important**: Use different values for production! Never reuse staging credentials.
For production, configure the same secrets as staging with `PRODUCTION_` prefix.
Use different values for production - never reuse staging credentials.
#### Optional: Turbo Cache

View file

@ -113,9 +113,8 @@ STAGING_SUPABASE_ANON_KEY=<anon-key>
STAGING_SUPABASE_SERVICE_ROLE_KEY=<service-role-key>
STAGING_AZURE_OPENAI_ENDPOINT=https://xxx.openai.azure.com
STAGING_AZURE_OPENAI_API_KEY=<api-key>
STAGING_JWT_SECRET=<jwt-secret>
STAGING_JWT_PUBLIC_KEY=<public-key>
STAGING_JWT_PRIVATE_KEY=<private-key>
# Note: JWT keys are managed automatically by Better Auth (EdDSA)
# Keys are stored in auth.jwks table - no manual configuration needed
```
#### Production Environment

View file

@ -573,8 +573,7 @@ services:
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-devpassword}
JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY}
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
# JWT keys managed automatically by Better Auth (EdDSA) - stored in auth.jwks table
depends_on:
postgres:
condition: service_healthy
@ -1689,7 +1688,6 @@ location ~* \.(html)$ {
| | `PORT` | 3001 | 3001 | 3001 | No |
| | `DATABASE_URL` | `postgresql://localhost:5432/manacore` | `postgresql://staging-db/manacore` | `postgresql://prod-db/manacore` | Yes |
| | `REDIS_HOST` | localhost | redis | redis | No |
| | `JWT_PRIVATE_KEY` | (dev key) | (staging key) | (prod key) | Yes |
| | `STRIPE_SECRET_KEY` | `sk_test_...` | `sk_test_...` | `sk_live_...` | Yes |
| **chat-backend** |
| | `PORT` | 3002 | 3002 | 3002 | No |

View file

@ -87,23 +87,12 @@ nano .env.production
# Required variables (never commit real values to git):
# - DATABASE_URL (Supabase connection strings)
# - JWT_PRIVATE_KEY (generate new RSA key pair)
# - AZURE_OPENAI_API_KEY
# - STRIPE_SECRET_KEY
# - REDIS_PASSWORD (use strong password)
```
**Generate JWT Keys:**
```bash
# Generate RSA key pair for JWT signing
ssh-keygen -t rsa -b 4096 -m PEM -f jwt_key
# Private key: jwt_key
# Public key: jwt_key.pub
# Convert to single-line format for .env
cat jwt_key | tr '\n' '|' # Replace | with \n in .env
cat jwt_key.pub | tr '\n' '|'
#
# Note: JWT keys are managed automatically by Better Auth (EdDSA)
# Keys are stored in auth.jwks table - no manual configuration needed
```
### Step 5: Deploy Shared Infrastructure

View file

@ -61,8 +61,6 @@ The generator reads `.env.development` and creates app-specific `.env` files wit
| Variable | Description | Used By |
|----------|-------------|---------|
| `MANA_CORE_AUTH_URL` | Auth service URL | All apps |
| `JWT_PRIVATE_KEY` | JWT signing key | mana-core-auth |
| `JWT_PUBLIC_KEY` | JWT verification key | All backends |
| `POSTGRES_USER` | Database user | Docker, backends |
| `POSTGRES_PASSWORD` | Database password | Docker, backends |
| `REDIS_HOST` | Redis host | mana-core-auth |

View file

@ -591,11 +591,12 @@ coverage/
**Key Secrets Required**:
- `POSTGRES_PASSWORD`
- `REDIS_PASSWORD`
- `JWT_PRIVATE_KEY`, `JWT_PUBLIC_KEY`
- `AZURE_OPENAI_API_KEY`
- `GOOGLE_GENAI_API_KEY`
- `SUPABASE_SERVICE_ROLE_KEY`
> **Note:** JWT keys are managed automatically by Better Auth (EdDSA) and stored in the `auth.jwks` database table.
---
## Network & Volume Strategy