Sicherheit
Dual-Auth
Abschnitt betitelt „Dual-Auth“Zwei Authentifizierungsmechanismen:
| Typ | Beschreibung | Lebensdauer |
|---|---|---|
| JWT | Kurzlebige Tokens via @fastify/jwt | Session-basiert |
| API-Key | Dauerhafter Key via X-API-Key Header | Bis zum Widerruf |
Das authenticate-Decorator prüft beide Varianten — zuerst JWT, dann API-Key als Fallback.
Token-Redaktion
Abschnitt betitelt „Token-Redaktion“JWT-Tokens in URL-Query-Parametern werden in Server-Logs automatisch als token=*** maskiert.
Rate-Limiting
Abschnitt betitelt „Rate-Limiting“- API-Key Generierung und Widerruf: max. 5 Anfragen pro Stunde
- KI-Rezeptüberarbeitung: max. 5 Anfragen pro 15 Minuten
KI-Prompt-Schutz
Abschnitt betitelt „KI-Prompt-Schutz“Bei der KI-Rezeptüberarbeitung werden Nutzer-Eingaben in Delimiter-Blöcke eingebettet und dürfen nur als inhaltliche Anweisung interpretiert werden. Der System-Prompt weist die KI explizit an, Anweisungen außerhalb des Rezept-Kontexts zu ignorieren. Der KI-Output wird durch sanitizeAiRecipe() sanitiert (Längenlimits, Typ-Validierung, Wertebereichsprüfung) und zusätzlich strukturell validiert (mind. 1 Zutat, 1 Zubereitungsschritt, nicht-leerer Titel).
Datenbankindex
Abschnitt betitelt „Datenbankindex“Unique-Index auf api_key (WHERE NOT NULL) für schnelle Lookups und Eindeutigkeit.
XSS-Schutz
Abschnitt betitelt „XSS-Schutz“Das Tampermonkey-Userscript escaped alle Fehlermeldungen (escapeHtml()) bevor sie ins DOM eingefügt werden.
Userscript-Sicherheit
Abschnitt betitelt „Userscript-Sicherheit“@connect-Einschränkung — Userscript darf nur mit dem konfigurierten API-Host kommunizieren (kein@connect *)GM_setValue— Konfiguration in Tampermonkey-Storage statt inlocalStorageder REWE-Domain
Bring!-Verschlüsselung
Abschnitt betitelt „Bring!-Verschlüsselung“Bring!-Passwörter werden AES-256-GCM-verschlüsselt in der SQLite-Datenbank gespeichert.
Admin-Schutz
Abschnitt betitelt „Admin-Schutz“requireAdmin nutzt das zentrale authenticate-Decorator (API-Key-kompatibel) statt direktem jwtVerify.
Haushalt-Zugriffskontrolle
Abschnitt betitelt „Haushalt-Zugriffskontrolle“Alle Haushalt-bezogenen Endpunkte prüfen die Mitgliedschaft über isHouseholdMember(). Der resolveHousehold-Decorator:
- Authentifiziert den Benutzer (JWT oder API-Key)
- Liest den
X-Household-Id-Header - Validiert die Mitgliedschaft — bei ungültigem Haushalt gibt es
403 Forbidden - Setzt
request.householdIdfür alle nachfolgenden Queries
SSE-Authentifizierung
Abschnitt betitelt „SSE-Authentifizierung“Da die native EventSource-API keine Custom-Header unterstützt, wird das JWT-Token als Query-Parameter (?token=...) akzeptiert. Das Token wird serverseitig manuell via fastify.jwt.verify() geprüft.
Einladungscodes
Abschnitt betitelt „Einladungscodes“- 8 Zeichen, alphanumerisch, mittels
crypto.randomBytes()generiert - 48 Stunden gültig, danach nicht mehr verwendbar
- Einmalverwendung — nach erfolgreichem Beitritt nicht erneut nutzbar
Share-Tokens
Abschnitt betitelt „Share-Tokens“- 32 Byte, hex-encoded (
crypto.randomBytes(32)) - 7 Tage gültig (konfigurierbar per
expires_days-Parameter) - Öffentlicher Zugriff zeigt nur Rezeptdaten — keine sensiblen Felder (User-ID, Haushalt-ID etc.)