docs: Pentest-Runden 11 + 12 in SECURITY-HARDENING + README aktualisieren
SECURITY-HARDENING.md: - Runde 11 "Externer Pentest-Folge: Header-Hygiene + Klartext-Audit": HSTS-Doppel-Header weg, Cache-Control je nach Pfad differenziert, CSP No-Fallback-Direktiven + frame-ancestors auf 'self', BREACH- Mitigation via gzip off im Reverse-Proxy für /api/*, Server-/ X-Served-By-Banner entfernt, Audit-Log für die 6 Klartext-Passwort- Read-Endpoints (CRITICAL). - Runde 12 "JWT raus aus localStorage": Branchenstandard-Refresh-Cookie- Pattern für die SPA. Access-Token (15 min) nur in JS-Memory, Refresh-Token (7d) im httpOnly-Cookie. Auth-Middleware verweigert Refresh-Tokens als Bearer (type-Claim). Axios-Interceptor mit Single-Flight-Refresh-Retry. Tabelle der Live-Tests. README.md: - Tech-Stack-Auth-Zeile beschreibt jetzt die Access/Refresh-Architektur - .env-Beispiel: JWT_EXPIRES_IN=15m + neue JWT_REFRESH_EXPIRES_IN=7d - Production-Deployment-Hinweis: Frontend und API müssen über dieselbe Origin laufen (SameSite=Strict-Cookie), sonst funktioniert /auth/refresh cross-site nicht und User wird alle 15 min ausgeloggt Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,9 @@ Web-basiertes CRM-System für Kundenverwaltung mit Verträgen (Energie, Telekomm
|
||||
- **Backend**: Node.js, Express 4.x, TypeScript
|
||||
- **Datenbank**: MariaDB
|
||||
- **ORM**: Prisma
|
||||
- **Auth**: JWT mit Rollen-basierter Zugriffskontrolle
|
||||
- **Auth**: JWT-Access-Token (Memory, 15 min) + Refresh-Token im httpOnly-Cookie
|
||||
(7 Tage). Rollen-basierte Zugriffskontrolle. XSS klaut maximal einen
|
||||
15-min-Access-Token, der Refresh-Cookie ist JS-unzugänglich.
|
||||
|
||||
> **Hinweis zu Express 5:** Das Projekt verwendet bewusst Express 4.x (nicht 5.x). Express 5 ist seit Jahren in der Beta-Phase und noch nicht offiziell stable. Bei der Installation darauf achten, dass `@types/express` zur Express-Version passt:
|
||||
> - Express 4.x → `@types/express@^4.17.x`
|
||||
@@ -124,9 +126,14 @@ Die `.env`-Datei sollte folgende Werte enthalten:
|
||||
# Database
|
||||
DATABASE_URL="mysql://root:rootpassword@localhost:3306/opencrm"
|
||||
|
||||
# JWT
|
||||
# JWT – Access-/Refresh-Token-Pattern (SPA-Standard)
|
||||
# Access-Token (Bearer-Header, nur im Browser-Memory, kurzlebig)
|
||||
# Refresh-Token (httpOnly-Cookie, lang)
|
||||
# Beide werden mit JWT_SECRET signiert; Refresh wird nur am
|
||||
# /api/auth/refresh-Endpoint akzeptiert (type-Claim).
|
||||
JWT_SECRET="change-this-to-a-very-long-random-secret-in-production"
|
||||
JWT_EXPIRES_IN="7d"
|
||||
JWT_EXPIRES_IN="15m" # Access-Token-Lifetime (Default: 15m)
|
||||
JWT_REFRESH_EXPIRES_IN="7d" # Refresh-Token-Lifetime (Default: 7d)
|
||||
|
||||
# Encryption (for portal credentials) - generate with: openssl rand -hex 32
|
||||
ENCRYPTION_KEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
@@ -207,6 +214,13 @@ Plus:
|
||||
|
||||
- **Reverse-Proxy** (Nginx/Plesk) so konfigurieren, dass `X-Forwarded-For` hart auf
|
||||
die echte Client-IP gesetzt wird (nicht nur angefügt) – sonst Rate-Limit-Bypass möglich.
|
||||
- **Frontend + API müssen über dieselbe Origin laufen.** Die Auth nutzt einen
|
||||
httpOnly-Refresh-Cookie mit `SameSite=Strict; Path=/api/auth` – wenn Frontend
|
||||
und API auf getrennten Origins liegen (z.B. `crm.example.de` vs.
|
||||
`api.example.de`), schickt der Browser das Cookie cross-site nicht mit
|
||||
und der `/auth/refresh`-Endpoint kann den User nicht mehr nachladen
|
||||
(= alle 15 min Re-Login). Beim NPM-Setup landen Frontend und API automatisch
|
||||
auf derselben Domain via Proxy-Path.
|
||||
- **Default-Admin-Passwort ändern** (admin@admin.com / admin).
|
||||
- **Manuelle Test-Checkliste** aus [docs/TESTING.md](docs/TESTING.md) einmal komplett
|
||||
durchklicken.
|
||||
|
||||
Reference in New Issue
Block a user