added mfa

This commit is contained in:
2026-05-24 08:37:27 +00:00
parent a1d9ed86e1
commit 3ab54f812a
10 changed files with 398 additions and 33 deletions
+36 -16
View File
@@ -158,8 +158,9 @@ func handleAuth(w http.ResponseWriter, r *http.Request) {
return
}
username := strings.TrimSpace(r.FormValue("username"))
password := r.FormValue("password")
username := strings.TrimSpace(r.FormValue("username"))
password := r.FormValue("password")
totpCode := strings.TrimSpace(r.FormValue("totp_code"))
// Input bounds — reject obviously bad values before touching the hasher
if len(username) == 0 || len(username) > 64 || len(password) == 0 || len(password) > 1024 {
@@ -170,24 +171,43 @@ func handleAuth(w http.ResponseWriter, r *http.Request) {
return
}
if checkCreds(username, password) {
http.SetCookie(w, &http.Cookie{
Name: authCookieName,
Value: makeAuthToken(),
Path: "/",
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
MaxAge: int(authTokenTTL.Seconds()),
})
logAuthAttempt(r, username, true, "login_success")
w.Write([]byte(`{"ok":true}`)) //nolint:errcheck
} else {
time.Sleep(500 * time.Millisecond) // blunt brute-force deterrent
// Step 1: verify password
if !checkCreds(username, password) {
time.Sleep(500 * time.Millisecond)
logAuthAttempt(r, username, false, "invalid_credentials")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`{"error":"Invalid username or password"}`)) //nolint:errcheck
return
}
// Step 2: MFA (if enabled)
if appCreds.MFAEnabled && appCreds.MFASecret != "" {
if totpCode == "" {
// Signal to frontend: show TOTP input
w.Write([]byte(`{"mfa_required":true}`)) //nolint:errcheck
return
}
if !validateTOTP(appCreds.MFASecret, totpCode) {
time.Sleep(500 * time.Millisecond)
logAuthAttempt(r, username, false, "invalid_totp")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`{"error":"Invalid authenticator code"}`)) //nolint:errcheck
return
}
}
// All checks passed — issue auth cookie
http.SetCookie(w, &http.Cookie{
Name: authCookieName,
Value: makeAuthToken(),
Path: "/",
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
MaxAge: int(authTokenTTL.Seconds()),
})
logAuthAttempt(r, username, true, "login_success")
w.Write([]byte(`{"ok":true}`)) //nolint:errcheck
}
func handleWS(w http.ResponseWriter, r *http.Request) {