# 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. 1) 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) konfiguriere `express-session` mit `connect-sqlite3`: ```js 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 } })); ``` - Abnahme: Session-Cookie (`sid`) wird gesetzt nach Login, cookie-Flags korrekt. 2) Login-Endpoint (Admin) - Ziel: Admin kann sich mit Benutzername/Passwort anmelden; Backend erstellt Session. - Schritte: - Füge `POST /auth/login` hinzu, prüft Credentials (z. B. gegen environment-stored admin user/pass oder htpasswd), legt `req.session.user = { role: 'admin' }` an und `req.session.csrfToken = randomHex()` an. - Rückgabe: 200 OK. Cookie wird automatisch gesetzt (`credentials: 'include'` vom Frontend). - Abnahme: Nach `POST /auth/login` existiert `req.session.user` und `req.session.csrfToken`. 3) CSRF-Endpoint + Middleware - Ziel: Session-gebundenen CSRF-Token ausgeben und Requests schützen. - Schritte: - Endpoint `GET /auth/csrf-token` gibt `{ csrfToken: req.session.csrfToken }` zurück (nur wenn eingeloggt). - Middleware `requireCsrf` prüft `req.headers['x-csrf-token'] === req.session.csrfToken` für state-changing Methoden. - Abnahme: state-changing Admin-Requests ohne oder mit falschem `X-CSRF-Token` bekommen `403`. 4) 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 sie `req.session.user && req.session.user.role === 'admin'` prüft; falls nicht gesetzt → `403`. - Abnahme: `GET /api/admin/*` ohne Session → `403`; mit gültiger Session → durchgelassen. 5) Frontend-Änderungen (adminApi) - Ziel: Frontend sendet keine Admin-Bearer-Tokens mehr; verwendet Cookie-Session + CSRF-Header. - Schritte: - Entferne in `frontend/src/services/adminApi.js` die Abhängigkeit von `process.env.REACT_APP_ADMIN_API_KEY`. - Passe `adminFetch`/`adminRequest` an: bei Requests setze `credentials: 'include'` und füge `X-CSRF-Token` Header (Token bezieht Frontend über `GET /auth/csrf-token` nach Login). - Dokumentiere in `frontend/README` oder Code-Kommentar, dass Admin-UI nach Login `fetch('/auth/csrf-token', { credentials: 'include' })` aufruft. - Abnahme: `adminApi.js` sendet keine Bearer-Header; admin Requests beinhalten `credentials: 'include'` und `X-CSRF-Token`. 6) Entfernen von Admin-Key aus Frontend Build/Compose/Dockerfile - Ziel: Keine Weitergabe von `ADMIN_API_KEY` an `frontend` und kein Kopieren sensibler `.env` in Frontend-Image. - Schritte: - Entferne Zeile `- REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}` aus `docker/prod/docker-compose.yml`. - Entferne `COPY docker/prod/frontend/config/.env ./.env` aus `docker/prod/frontend/Dockerfile` oder stelle sicher, dass diese Datei ausschließlich non-sensitive Keys enthält. - Dokumentiere in `FeatureRequests/FEATURE_REQUEST-security.md` welche Keys im runtime-`env.sh` erlaubt sind (z. B. `API_URL`, `APP_VERSION`). - Abnahme: `docker-compose` enthält keine Übergabe an `frontend`; Build und Image enthalten keine Production-Secrets. 7) Secrets-Handling / Deployment - Ziel: Secrets nur in Backend-Umgebung bereitstellen. - Schritte: - Setze `ADMIN_API_KEY` und `ADMIN_SESSION_SECRET` in CI/CD Secrets oder Docker Secrets und referenziere sie nur im `backend` Service. - Beispiel-Dokumentation für CI: wie man Secret in GitLab/GitHub Actions setzt und an Container übergibt. - Abnahme: Secrets sind nicht in Repo/Images; `docker inspect` der frontend-Container zeigt keinen Admin-Key. 8) Tests & CI-Checks - Ziel: Automatisierte Verifikation der Sicherheitsregeln. - Schritte: - Integrationstest 1: `GET /api/admin/some` ohne Session → expect 403. - Integrationstest 2: `POST /auth/login` with admin credentials → expect Set-Cookie; then `GET /auth/csrf-token` → receive token; then `POST /api/admin/action` with `X-CSRF-Token` → expect 200. - Build-scan-Check: CI Schritt `rg REACT_APP_ADMIN_API_KEY build/ || true` fails if found. - Abnahme: Tests grün; CI verweigert Merge wenn Build enthält Admin-Key. 9) Key-Leak Reaktion (konkrete Anweisungen) - Ziel: Falls ein Admin-Key geleakt wurde, sichere, koordinierte Rotation. - Schritte: - Scannen: `trufflehog --regex --entropy=True .` oder `git-secrets scan`. - Entfernen: `git-filter-repo --replace-text passwords.txt` oder `bfg --replace-text passwords.txt` (siehe docs). - Rotation: Erzeuge neuen Key (openssl rand -hex 32), update CI secret, redeploy Backend. - Hinweis: History-Rewrite ist invasiv; kommuniziere mit Team und informiere Contributors. 10) Dokumentation - Ziel: Abschlussdokumentation aktualisiert. - Schritte: - Ergänze `AUTHENTICATION.md` um Login/Session/CSRF-Flow und Secret-Handling. - Ergänze `FeatureRequests/FEATURE_REQUEST-security.md` mit Implementations-Links (Patches/PRs). 11) MIGRATION-GUIDE Anpassung (unbedingt) - Ziel: Die `frontend/MIGRATION-GUIDE.md` spiegelt 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_KEY` in `frontend/.env` zu setzen und dieselbe Variable an `frontend` im `docker-compose.yml` weiterzugeben. 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_KEY` in Frontend `.env` oder 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_KEY` darf nur dem `backend`-Service übergeben werden; entferne die Weitergabe an `frontend` (Zeile `- REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}`). - Ersetze lokale Testanweisungen, die Frontend mit `REACT_APP_ADMIN_API_KEY` starten, 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. - Abnahme: `frontend/MIGRATION-GUIDE.md` enthä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.md` einen 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/.env` enthält `REACT_APP_ADMIN_API_KEY` in der Arbeitskopie (lokal). Die Datei ist in `.gitignore` und wird nicht ins Git-Repository getrackt, ist aber sensibel und darf nicht in Builds/Images gelangen. - `docker/prod/docker-compose.yml` injiziert `REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}` in den `frontend`-Service — der Key kann so in den gebauten Frontend-Bundles landen. - `frontend/src/services/adminApi.js` liest `process.env.REACT_APP_ADMIN_API_KEY` und sendet den Bearer-Token clientseitig mit Admin-Requests. - Das Production-Frontend-Dockerfile kopiert `docker/prod/frontend/config/.env` in das Laufzeit-Image und führt zur Startzeit ein `env.sh` aus, das `env-config.js` erzeugt (`window._env_`), was sensible Werte im Browser verfügbar machen kann, falls sie in `.env` landen. - 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_KEY` wird 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 internen `ADMIN_API_KEY` gearbeitet. - Secrets & Build: - Keine Secrets (z. B. `ADMIN_API_KEY`) im Frontend-Quellcode, in `frontend/.env`, in `env-config.js` oder in gebauten Bundles. - `docker/prod/docker-compose.yml` darf `ADMIN_API_KEY` nur dem `backend`-Service bereitstellen; keine Weitergabe an `frontend`. - `Dockerfile` des Frontends darf keine Produktion-`.env` kopieren, die Secrets enthält. - 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. Akzeptanzkriterien (klar messbar, für Tests durch eine KI/Dev) - Funktional: - Unauthentifizierte Requests an `/api/admin/*` erhalten `403 Forbidden`. - Admin-Login-Endpoint existiert und setzt ein HttpOnly-Cookie; angemeldete Admins erreichen `/api/admin/*` erfolgreich. - Artefakte / Repo: - `frontend`-Bundle (der gebaute `build/`-Ordner) enthält nicht den Wert von `ADMIN_API_KEY` (automatischer Scan: kein Vorkommen des Key-Strings). - `frontend/.env` enthält keine `REACT_APP_ADMIN_API_KEY`-Zeile in Produktion; `docker/prod/docker-compose.yml` enthält keine Weitergabe des Keys an `frontend`. - Sicherheit & Ops: - Dokumentation: In `AUTHENTICATION.md` und in dieser Feature-Request-Datei wird der neue Login-Flow und Hinweis zum Secret-Handling vermerkt. - Dokumentation: In `AUTHENTICATION.md` und 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/.env` oder 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'` oder `git grep -n "REACT_APP_ADMIN_API_KEY" $(git rev-list --all)` oder nutzen `truffleHog`/`git-secrets`. - Entfernen aus History: `git-filter-repo` oder `bfg-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. Nicht-funktionale Anforderungen - Use Session-Cookies: Cookies müssen `HttpOnly`, `Secure` und `SameSite=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.js` in `docker/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 aktuell `process.env.REACT_APP_ADMIN_API_KEY` und setzt den Bearer-Token clientseitig. - `frontend/.env` — enthält aktuell `REACT_APP_ADMIN_API_KEY`. - `docker/prod/docker-compose.yml` — injiziert `REACT_APP_ADMIN_API_KEY=${ADMIN_API_KEY}` in `frontend`. - `docker/prod/frontend/Dockerfile` — kopiert `docker/prod/frontend/config/.env` in das Image und führt `env.sh` aus, das `env-config.js` erzeugt (`window._env_`). - `docker/prod/frontend/config/env.sh` — generiert zur Laufzeit `env-config.js` aus `.env`. - `docker/prod/frontend/config/htpasswd` — existierender Schutz der Admin-UI via nginx. - Erwartung an eine KI-Implementierung: - Verstehe die Codebasis (insbesondere `frontend/src/*` und `backend/src/*`) und identifiziere alle Stellen, die `REACT_APP_ADMIN_API_KEY` oder `ADMIN_API_KEY` verwenden 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. 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.md` weist 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` (oder `better-sqlite3` backend). Konfiguration: - Session-Cookie: `HttpOnly`, `Secure` (Prod), `SameSite=Strict` (oder `Lax` wenn externe callbacks nötig), `maxAge` angemessen (z. B. 8h). - Session-Secret aus sicherer Quelle (Backend `ADMIN_SESSION_SECRET`), nicht im Repo. - 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: 1. Bei Login: generiere `req.session.csrfToken = randomHex()` auf dem Server. 2. Exponiere Endpoint `GET /auth/csrf-token` (nur für eingeloggte Sessions), der das Token im JSON zurückgibt. 3. Frontend ruft `/auth/csrf-token` nach Login (`credentials: 'include'`) und speichert Token im JS-Scope. 4. Bei state-changing Requests sendet Frontend `X-CSRF-Token: ` Header. 5. Server-Middleware vergleicht Header mit `req.session.csrfToken` und verwirft bei Mismatch (403). - 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. - Entfernen von Admin-Key aus Frontend/Build (konkrete Änderungen) - `frontend/src/services/adminApi.js`: entferne Nutzung von `process.env.REACT_APP_ADMIN_API_KEY`. Passe `adminRequest` so an, dass `credentials: '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}` unter `frontend`. - `docker/prod/frontend/Dockerfile`: entferne `COPY docker/prod/frontend/config/.env ./.env` (oder stelle sicher, dass die Datei keine Secrets enthält). Vermeide Prod `.env` Kopie 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_KEY` und `ADMIN_SESSION_SECRET` via CI/CD Secret Store oder Docker Secrets bereitstellen. - Beispiel (Docker secret): erstelle Secret im Swarm/K8s und referenziere es nur im `backend`-Service. - Tests / Abnahme (automatisierbar) - Integrationstest 1: `GET /api/admin/*` ohne Session → `403`. - Integrationstest 2: Login-Flow → setze Session-Cookie → `POST /api/admin/*` mit gültigem `X-CSRF-Token` → `200`. - Build-Scan: nach Build `grep -R "" build/` oder `rg REACT_APP_ADMIN_API_KEY build/` → kein Treffer. - 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.md` und in Release-Notes. 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. ---