- replace bearer auth with session+CSRF flow and add admin user directory - update frontend moderation flow, force password change gate, and new CLI - refresh changelog/docs/feature plan + ensure swagger dev experience
20 KiB
- erstelle ein Branch namens
feature/securityaus dem aktuellenmainBranch. - erstelle eine Datei
FeatureRequests/FEATURE_PLAN-security.mdin der du die Umsetzungsaufgaben dokumentierst (siehe unten) und darin die TODO Liste erstellst und aktuallisierst. - Stelle mir Fragen bezüglich der Umsetzung
- Verstehe, wie bisher im Frontend die UI aufgebaut ist (modular, keine inline css, globale app.css)
- Implementiere die untenstehenden Aufgaben Schritt für Schritt.
FEATURE_REQUEST: Security — Server-seitige Sessions für Admin-API
Umsetzungsaufgaben (konkret & eindeutig für KI / Entwickler)
Die folgenden Aufgaben sind Schritt-für-Schritt auszuführen. Jede Aufgabe enthält das gewünschte Ergebnis und minimalen Beispielcode oder Befehle. Die KI/Entwickler sollen die Änderungen als Code-Patches anlegen, Tests hinzufügen und die Dokumentation aktualisieren.
-
Session-Store & Session-Konfiguration
- Ziel: Server-seitige Sessions für Admin-Login verfügbar machen.
- Schritte:
- Installiere Packages:
npm install express-session connect-sqlite3 --save(Backend). - In
backend/src/server.js(oder Entrypoint) konfiguriereexpress-sessionmitconnect-sqlite3:const session = require('express-session'); const SQLiteStore = require('connect-sqlite3')(session); app.use(session({ store: new SQLiteStore({ db: 'sessions.sqlite' }), secret: process.env.ADMIN_SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'Strict', maxAge: 8*60*60*1000 } }));
- Installiere Packages:
- Abnahme: Session-Cookie (
sid) wird gesetzt nach Login, cookie-Flags korrekt.
-
Login-Endpoint (Admin)
- Ziel: Admin kann sich mit Benutzername/Passwort anmelden; Backend erstellt Session.
- Schritte:
- Füge
POST /auth/loginhinzu, prüft Credentials (z. B. gegen environment-stored admin user/pass oder htpasswd), legtreq.session.user = { role: 'admin' }an undreq.session.csrfToken = randomHex()an. - Rückgabe: 200 OK. Cookie wird automatisch gesetzt (
credentials: 'include'vom Frontend).
- Füge
- Abnahme: Nach
POST /auth/loginexistiertreq.session.userundreq.session.csrfToken.
-
CSRF-Endpoint + Middleware
- Ziel: Session-gebundenen CSRF-Token ausgeben und Requests schützen.
- Schritte:
- Endpoint
GET /auth/csrf-tokengibt{ csrfToken: req.session.csrfToken }zurück (nur wenn eingeloggt). - Middleware
requireCsrfprüftreq.headers['x-csrf-token'] === req.session.csrfTokenfür state-changing Methoden.
- Endpoint
- Abnahme: state-changing Admin-Requests ohne oder mit falschem
X-CSRF-Tokenbekommen403.
-
Backend-Auth-Middleware für Admin-API
- Ziel: Alle
/api/admin/*Endpoints prüfen Session statt Client-Token. - Schritte:
- Ersetze oder erweitere bestehende Admin-Auth-Middleware (
middlewares/auth.js) so, dass siereq.session.user && req.session.user.role === 'admin'prüft; falls nicht gesetzt →403.
- Ersetze oder erweitere bestehende Admin-Auth-Middleware (
- Abnahme:
GET /api/admin/*ohne Session →403; mit gültiger Session → durchgelassen.
- Ziel: Alle
-
Frontend-Änderungen (adminApi)
- Ziel: Frontend sendet keine Admin-Bearer-Tokens mehr; verwendet Cookie-Session + CSRF-Header.
- Schritte:
- Entferne in
frontend/src/services/adminApi.jsdie Abhängigkeit vonprocess.env.REACT_APP_ADMIN_API_KEY. - Passe
adminFetch/adminRequestan: bei Requests setzecredentials: 'include'und fügeX-CSRF-TokenHeader (Token bezieht Frontend überGET /auth/csrf-tokennach Login). - Dokumentiere in
frontend/READMEoder Code-Kommentar, dass Admin-UI nach Loginfetch('/auth/csrf-token', { credentials: 'include' })aufruft.
- Entferne in
- Abnahme:
adminApi.jssendet keine Bearer-Header; admin Requests beinhaltencredentials: 'include'undX-CSRF-Token.
-
Entfernen von Admin-Key aus Frontend Build/Compose/Dockerfile
- Ziel: Keine Weitergabe von
ADMIN_API_KEYanfrontendund kein Kopieren sensibler.envin Frontend-Image. - Schritte:
- Entferne Zeile
- REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}ausdocker/prod/docker-compose.yml. - Entferne
COPY docker/prod/frontend/config/.env ./.envausdocker/prod/frontend/Dockerfileoder stelle sicher, dass diese Datei ausschließlich non-sensitive Keys enthält. - Dokumentiere in
FeatureRequests/FEATURE_REQUEST-security.mdwelche Keys im runtime-env.sherlaubt sind (z. B.API_URL,APP_VERSION).
- Entferne Zeile
- Abnahme:
docker-composeenthält keine Übergabe anfrontend; Build und Image enthalten keine Production-Secrets.
- Ziel: Keine Weitergabe von
-
Secrets-Handling / Deployment
- Ziel: Secrets nur in Backend-Umgebung bereitstellen.
- Schritte:
- Setze
ADMIN_API_KEYundADMIN_SESSION_SECRETin CI/CD Secrets oder Docker Secrets und referenziere sie nur imbackendService. - Beispiel-Dokumentation für CI: wie man Secret in GitLab/GitHub Actions setzt und an Container übergibt.
- Setze
- Abnahme: Secrets sind nicht in Repo/Images;
docker inspectder frontend-Container zeigt keinen Admin-Key.
-
Tests & CI-Checks
- Ziel: Automatisierte Verifikation der Sicherheitsregeln.
- Schritte:
- Integrationstest 1:
GET /api/admin/someohne Session → expect 403. - Integrationstest 2:
POST /auth/loginwith admin credentials → expect Set-Cookie; thenGET /auth/csrf-token→ receive token; thenPOST /api/admin/actionwithX-CSRF-Token→ expect 200. - Build-scan-Check: CI Schritt
rg REACT_APP_ADMIN_API_KEY build/ || truefails if found.
- Integrationstest 1:
- Abnahme: Tests grün; CI verweigert Merge wenn Build enthält Admin-Key.
-
Key-Leak Reaktion (konkrete Anweisungen)
- Ziel: Falls ein Admin-Key geleakt wurde, sichere, koordinierte Rotation.
- Schritte:
- Scannen:
trufflehog --regex --entropy=True .odergit-secrets scan. - Entfernen:
git-filter-repo --replace-text passwords.txtoderbfg --replace-text passwords.txt(siehe docs). - Rotation: Erzeuge neuen Key (openssl rand -hex 32), update CI secret, redeploy Backend.
- Scannen:
- Hinweis: History-Rewrite ist invasiv; kommuniziere mit Team und informiere Contributors.
-
Dokumentation
- Ziel: Abschlussdokumentation aktualisiert.
- Schritte:
- Ergänze
AUTHENTICATION.mdum Login/Session/CSRF-Flow und Secret-Handling. - Ergänze
FeatureRequests/FEATURE_REQUEST-security.mdmit Implementations-Links (Patches/PRs).
- Ergänze
- MIGRATION-GUIDE Anpassung (unbedingt)
- Ziel: Die
frontend/MIGRATION-GUIDE.mdspiegelt nicht mehr den sicheren Produktions-Workflow. Sie muss aktualisiert werden, damit Entwickler/KI keine unsicheren Anweisungen (Admin-Key im Frontend) ausführen. - Aktueller Stand (zu prüfen): Die MIGRATION-GUIDE enthält Anweisungen,
REACT_APP_ADMIN_API_KEYinfrontend/.envzu setzen und dieselbe Variable anfrontendimdocker-compose.ymlweiterzugeben. Dies steht im direkten Widerspruch zur hier geforderten serverseitigen Session-Lösung. - Erforderliche Änderungen in
frontend/MIGRATION-GUIDE.md(konkret):- Entferne oder ersetze alle Anweisungen, die
REACT_APP_ADMIN_API_KEYin Frontend.envoder Build-Umgebungen für Production setzen. - Ersetze Fetch-/Axios-Beispiele, die
Authorization: Bearer ${process.env.REACT_APP_ADMIN_API_KEY}setzen, durch die neue Anleitung: Login →GET /auth/csrf-token→fetch(..., { credentials: 'include', headers: { 'X-CSRF-Token': csrfToken } }). - Passe das Docker-Beispiel an:
ADMIN_API_KEYdarf nur dembackend-Service übergeben werden; entferne die Weitergabe anfrontend(Zeile- REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}). - Ersetze lokale Testanweisungen, die Frontend mit
REACT_APP_ADMIN_API_KEYstarten, durch Login-/Session-Testschritte (siehe Tasks 2/3/8). - Ergänze Hinweis zur CI/Build-Scan-Prüfung: CI muss prüfen, dass gebaute
build/keine Admin-Key-Strings enthält.
- Entferne oder ersetze alle Anweisungen, die
- Abnahme:
frontend/MIGRATION-GUIDE.mdenthält keine Production-Anweisungen, die Admin-Secrets ins Frontend bringen; stattdessen ist der Session-Flow dokumentiert und verlinkt.
Hinweis für die Implementierung
- Ergänze in
FeatureRequests/FEATURE_REQUEST-security.mdeinen Link/Verweis zur überarbeiteten MIGRATION-GUIDE-Version in der PR/Release-Notes, damit Reviewer die Änderung nachvollziehen können.
Rolle der implementierenden KI/Dev
- Erzeuge konkrete Code-Patches, führe lokale Tests aus, öffne PR mit Änderungen und Tests.
- Stelle sicher, dass alle Abnahme-Kriterien (oben) automatisiert oder manuell prüfbar sind.
Mit diesen Aufgaben sind die vorher offenen Fragen in eindeutige, ausführbare Schritte übersetzt. Bitte bestätige, welche Aufgaben ich automatisch umsetzen soll (z. B. 1 = Compose/Docker-Änderungen; 2 = Frontend adminApi.js Patch; 3 = Backend Session+CSRF minimal-Implementierung; oder all).
Hintergrund (Ist-Stand)
- Aktuell existieren folgende sicherheitskritische Zustände im Repository:
frontend/.enventhältREACT_APP_ADMIN_API_KEYin der Arbeitskopie (lokal). Die Datei ist in.gitignoreund wird nicht ins Git-Repository getrackt, ist aber sensibel und darf nicht in Builds/Images gelangen.docker/prod/docker-compose.ymlinjiziertREACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}in denfrontend-Service — der Key kann so in den gebauten Frontend-Bundles landen.frontend/src/services/adminApi.jsliestprocess.env.REACT_APP_ADMIN_API_KEYund sendet den Bearer-Token clientseitig mit Admin-Requests.- Das Production-Frontend-Dockerfile kopiert
docker/prod/frontend/config/.envin das Laufzeit-Image und führt zur Startzeit einenv.shaus, dasenv-config.jserzeugt (window._env_), was sensible Werte im Browser verfügbar machen kann, falls sie in.envlanden. - Die Moderation-Weboberfläche ist zusätzlich durch
htpasswd/nginx HTTP Basic Auth geschützt — das schützt das UI, aber nicht die API-Endpoints ausreichend.
Problemstellung (warum es ein Problem ist)
- Ein im Frontend sichtbarer Admin-Key ist öffentlich und ermöglicht Missbrauch (API-Calls mit Admin-Rechten von jedem Browser).
- Das serverseitige Secret
ADMIN_API_KEYwird derzeit in Artefakte/Images injiziert und kann geleakt werden. - HTTP Basic Auth vor der UI ist nützlich, aber kein Ersatz für serverseitige API-Authentifizierung; API-Endpunkte müssen eigenständig prüfen.
Ziel (Soll-Stand, aus Kundensicht)
- Admin-Funktionen sind nur nach sicherer Anmeldung erreichbar.
- Der geheime Admin-Key verbleibt ausschließlich auf dem Server/Backend und wird nicht in Frontend-Code, Images oder öffentlich zugängliche Dateien geschrieben.
- Frontend kommuniziert nach Anmeldung mit dem Backend, ohne je den Admin-Key im Browser zu speichern.
Anforderungen (aus Sicht des Auftraggebers, umsetzbar durch eine KI)
-
Authentifizierung:
- Einführung eines serverseitigen Login-Flows für Admins (Session-Cookies, HttpOnly, Secure, SameSite).
- Nach erfolgreicher Anmeldung erhält der Admin-Browser ein HttpOnly-Cookie; dieses Cookie erlaubt Zugriff auf geschützte
/api/admin/*-Endpoints. - Backend validiert alle
/api/admin/*-Requests anhand der Session; nur dann wird mit dem internenADMIN_API_KEYgearbeitet.
-
Secrets & Build:
- Keine Secrets (z. B.
ADMIN_API_KEY) im Frontend-Quellcode, infrontend/.env, inenv-config.jsoder in gebauten Bundles. docker/prod/docker-compose.ymldarfADMIN_API_KEYnur dembackend-Service bereitstellen; keine Weitergabe anfrontend.Dockerfiledes Frontends darf keine Produktion-.envkopieren, die Secrets enthält.
- Keine Secrets (z. B.
-
Betrieb & Infrastruktur:
- Bestehende
htpasswd-Absicherung der Admin-UI kann beibehalten werden als zusätzliche Hürde, ist aber nicht die einzige Schutzmaßnahme. - Empfehlung:
ADMIN_API_KEYüber sichere Secret-Mechanismen bereitstellen (CI/CD secret store, Docker Secrets, Swarm/K8s Secrets) — dies ist ein Hinweis, keine Pflichtanweisung.
- Bestehende
Akzeptanzkriterien (klar messbar, für Tests durch eine KI/Dev)
-
Funktional:
- Unauthentifizierte Requests an
/api/admin/*erhalten403 Forbidden. - Admin-Login-Endpoint existiert und setzt ein HttpOnly-Cookie; angemeldete Admins erreichen
/api/admin/*erfolgreich.
- Unauthentifizierte Requests an
-
Artefakte / Repo:
frontend-Bundle (der gebautebuild/-Ordner) enthält nicht den Wert vonADMIN_API_KEY(automatischer Scan: kein Vorkommen des Key-Strings).frontend/.enventhält keineREACT_APP_ADMIN_API_KEY-Zeile in Produktion;docker/prod/docker-compose.ymlenthält keine Weitergabe des Keys anfrontend.
-
Sicherheit & Ops:
- Dokumentation: In
AUTHENTICATION.mdund in dieser Feature-Request-Datei wird der neue Login-Flow und Hinweis zum Secret-Handling vermerkt. - Dokumentation: In
AUTHENTICATION.mdund in dieser Feature-Request-Datei wird der neue Login-Flow und Hinweis zum Secret-Handling vermerkt. - Falls ein Key im Git-Verlauf existierte, ist die Rotation des Admin-Keys als Handlungsempfehlung dokumentiert.
- Falls
frontend/.envoder ein Admin-Key jemals in das Repository gelangt ist: Scannt die Git-History und entfernt das Secret aus der History, danach rotiert den Key. Empfohlene Tools/Schritte (kurz):- Finden:
git log --all -S 'part-of-key'odergit grep -n "REACT_APP_ADMIN_API_KEY" $(git rev-list --all)oder nutzentruffleHog/git-secrets. - Entfernen aus History:
git-filter-repooderbfg-repo-cleaner(z.B.bfg --replace-text passwords.txt --no-blob-protection) — danach Force-Push in ein neues Remote (Achtung: Auswirkungen auf Contributors). - Key-Rotation: Erzeuge neuen
ADMIN_API_KEY, setze ihn in der sicheren Backend-Umgebung (CI/CD secrets / Docker secret), redeploye Backend. - Hinweis: Diese Schritte sind invasiv für die Git-History; koordinieren mit Team bevor Ausführung.
- Finden:
- Dokumentation: In
Nicht-funktionale Anforderungen
- Use Session-Cookies: Cookies müssen
HttpOnly,SecureundSameSite=Strict(oder Lax falls nötig) gesetzt werden. - CSRF-Schutz: Bei Cookie-basierten Sessions muss ein CSRF-Schutzmechanismus vorhanden sein (z. B. double-submit-token oder CSRF-Header). Hinweis: CSRF-Mechanik ist zu implementieren, aber detaillierte Schritte sind nicht Teil dieses Requests.
- Kompatibilität: Änderungen dürfen Entwickler-Workflows nicht unnötig blockieren; Dev-Mode-Patterns (runtime
env-config.jsindocker/dev) können bestehen bleiben, jedoch klar getrennt von Prod.
Hinweise für die implementierende KI / das Dev-Team (kontextbezogen)
-
Aktueller Code-Pfade von Relevanz:
frontend/src/services/adminApi.js— liest aktuellprocess.env.REACT_APP_ADMIN_API_KEYund setzt den Bearer-Token clientseitig.frontend/.env— enthält aktuellREACT_APP_ADMIN_API_KEY.docker/prod/docker-compose.yml— injiziertREACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}infrontend.docker/prod/frontend/Dockerfile— kopiertdocker/prod/frontend/config/.envin das Image und führtenv.shaus, dasenv-config.jserzeugt (window._env_).docker/prod/frontend/config/env.sh— generiert zur Laufzeitenv-config.jsaus.env.docker/prod/frontend/config/htpasswd— existierender Schutz der Admin-UI via nginx.
-
Erwartung an eine KI-Implementierung:
- Verstehe die Codebasis (insbesondere
frontend/src/*undbackend/src/*) und identifiziere alle Stellen, dieREACT_APP_ADMIN_API_KEYoderADMIN_API_KEYverwenden oder weiterreichen. - Entferne clientseitige Verwendung des Admin-Keys; ersetze Aufrufe an Admin-API so, dass sie serverseitig autorisiert werden (Session-Check).
- Verifiziere durch automatische Tests (Integrationstest oder API-Call) dass
/api/admin/*ohne Session abgewiesen wird und mit Session funktioniert.
- Verstehe die Codebasis (insbesondere
Was der Auftraggeber (Ich) erwartet — kurz und klar
- Die Admin-Funktionen sind nur nach Anmeldung verfügbar.
- Keine Admin-Secrets gelangen in Frontend-Bundles, Images oder öffentlich zugängliche Dateien.
- Der existierende
htpasswd-Schutz darf bestehen bleiben, ist aber nicht alleinige Sicherheitsmaßnahme.
Abnahmekriterien (für das Review durch den Auftraggeber)
- Manuelle Überprüfung: Versuch, Admin-Endpoints ohne Login aufzurufen →
403. - Build-Review: gebaute Frontend-Dateien enthalten keinen Admin-Key.
- Dokumentation aktualisiert (
AUTHENTICATION.mdweist auf neue Session-Flow hin).
Offene Fragen / Optionen (für Entwickler/KI) — Empfehlung und Umsetzungsdetails
-
Session-Store (empfohlen: SQLite für Single-Host, Redis für Skalierung)
- Empfehlung für diese App: SQLite / file-basierter Session-Store (einfach zu betreiben, keine zusätzliche Infrastruktur).
- Umsetzung (Express): benutze
express-session+connect-sqlite3(oderbetter-sqlite3backend). Konfiguration:- Session-Cookie:
HttpOnly,Secure(Prod),SameSite=Strict(oderLaxwenn externe callbacks nötig),maxAgeangemessen (z. B. 8h). - Session-Secret aus sicherer Quelle (Backend
ADMIN_SESSION_SECRET), nicht im Repo.
- Session-Cookie:
- Skalierung: falls Cluster/Multiple hosts geplant, wechsle zu Redis (z.B.
connect-redis) und setze Redis via Docker/K8s Secret.
-
CSRF-Mechanik (empfohlen: session-bound CSRF token + Header)
- Empfehlung: Implementiere einen session-gebundenen CSRF-Token. Ablauf:
- Bei Login: generiere
req.session.csrfToken = randomHex()auf dem Server. - Exponiere Endpoint
GET /auth/csrf-token(nur für eingeloggte Sessions), der das Token im JSON zurückgibt. - Frontend ruft
/auth/csrf-tokennach Login (credentials: 'include') und speichert Token im JS-Scope. - Bei state-changing Requests sendet Frontend
X-CSRF-Token: <token>Header. - Server-Middleware vergleicht Header mit
req.session.csrfTokenund verwirft bei Mismatch (403).
- Bei Login: generiere
- Vorteil: HttpOnly-Session-Cookie bleibt geschützt; Token ist an Session gebunden.
- Alternative (schnell): Double-submit cookie (weniger robust, Token in non-HttpOnly cookie + Header); nur als kurzfristige Übergangslösung.
- Empfehlung: Implementiere einen session-gebundenen CSRF-Token. Ablauf:
-
Entfernen von Admin-Key aus Frontend/Build (konkrete Änderungen)
frontend/src/services/adminApi.js: entferne Nutzung vonprocess.env.REACT_APP_ADMIN_API_KEY. PasseadminRequestso an, dasscredentials: 'include'verwendet wird und kein Bearer-Token gesetzt wird.docker/prod/docker-compose.yml: lösche die Zeile- REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}unterfrontend.docker/prod/frontend/Dockerfile: entferneCOPY docker/prod/frontend/config/.env ./.env(oder stelle sicher, dass die Datei keine Secrets enthält). Vermeide Prod.envKopie in Image.docker/prod/frontend/config/env.sh: darf nur non-sensitive Werte (z. B.API_URL,APP_VERSION) schreiben; dokumentiere welche Keys erlaubt sind.
-
Secrets-Delivery / Deployment
- Backend-Secret
ADMIN_API_KEYundADMIN_SESSION_SECRETvia CI/CD Secret Store oder Docker Secrets bereitstellen. - Beispiel (Docker secret): erstelle Secret im Swarm/K8s und referenziere es nur im
backend-Service.
- Backend-Secret
-
Tests / Abnahme (automatisierbar)
- Integrationstest 1:
GET /api/admin/*ohne Session →403. - Integrationstest 2: Login-Flow → setze Session-Cookie →
POST /api/admin/*mit gültigemX-CSRF-Token→200. - Build-Scan: nach Build
grep -R "<part-of-admin-key>" build/oderrg REACT_APP_ADMIN_API_KEY build/→ kein Treffer.
- Integrationstest 1:
-
Key-Leak Reaktion
- Falls Key geleakt: sofort Key-Rotation, dokumentiere wie (generate new key, update backend secret, redeploy), und führe Git-History-Check wie in Abschnitt oben durch.
-
Operationale Hinweise
- Behalte
htpasswd-Schutz für Admin-UI als zusätzliche Zugangskontrolle, nicht als einzige Schutzmaßnahme. - Dokumentiere alle Änderungen in
AUTHENTICATION.mdund in Release-Notes.
- Behalte
Diese Empfehlungen sind aus Sicht einer sicheren, pragmatischen Umsetzung gewählt: sie minimieren Infrastruktur-Overhead (SQLite) und bieten klare, testbare CSRF/Session‑Mechaniken. Eine implementierende KI soll die obenstehenden Punkte in konkreten Code‑Patches umsetzen und automatisierte Tests hinzufügen.
Kontakt / Kontext
- Repo: Project-Image-Uploader — bestehende Struktur
docker/prod,frontend/,backend/beachten. - Hinweis: Diese Feature-Request-Datei benennt Missstände und Anforderungen; sie erwartet, dass ein Entwickler oder eine KI die Implementierung auf Code-Ebene vornimmt.