From 73c3d74098a3ccbacc6aa81faf3cf142af502a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Mon, 23 Mar 2026 22:22:58 +0100 Subject: [PATCH] =?UTF-8?q?fix(csrf):=20CSRF-Token=20in=20Login-Fehlerseit?= =?UTF-8?q?e=20fehlt=20=E2=80=94=20macht=20Retry-Versuch=20unm=C3=B6glich?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HandleLoginPost renderte Fehlerseiten (falsches Passwort, leere Felder) ohne CSRFToken in den Template-Daten. Das hidden field war leer, sodass jeder weitere Submit-Versuch mit "Ungültiger CSRF-Token" scheiterte. Fix: setCSRFCookie am Anfang des Handlers aufrufen und das Token in allen renderError-Pfaden an das Template übergeben. Co-Authored-By: Claude Sonnet 4.6 --- server/backend/internal/httpapi/manage/auth.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/server/backend/internal/httpapi/manage/auth.go b/server/backend/internal/httpapi/manage/auth.go index d82af3b..a42ffd8 100644 --- a/server/backend/internal/httpapi/manage/auth.go +++ b/server/backend/internal/httpapi/manage/auth.go @@ -76,13 +76,18 @@ func HandleLoginUI(authStore *store.AuthStore, screenStore *store.ScreenStore, c func HandleLoginPost(authStore *store.AuthStore, screenStore *store.ScreenStore, cfg config.Config) http.HandlerFunc { tmpl := template.Must(template.New("login").Parse(loginTmpl)) - renderError := func(w http.ResponseWriter, next, msg string) { - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.WriteHeader(http.StatusUnauthorized) - _ = tmpl.Execute(w, loginData{Error: msg, Next: next}) - } - return func(w http.ResponseWriter, r *http.Request) { + // K1: CSRF-Cookie erneuern und Token für Fehler-Re-Rendering bereitstellen. + // Das Token muss auch bei Fehlerantworten im Hidden-Field stehen, damit + // der nächste Submit-Versuch den CSRF-Check besteht. + csrfToken := setCSRFCookie(w, r, cfg.DevMode) + + renderError := func(w http.ResponseWriter, next, msg string) { + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusUnauthorized) + _ = tmpl.Execute(w, loginData{Error: msg, Next: next, CSRFToken: csrfToken}) + } + if err := r.ParseForm(); err != nil { renderError(w, "", "Ungültige Anfrage.") return