Merge SEC-11: use json.Marshal for audit details

This commit is contained in:
2026-03-13 01:06:55 -07:00
5 changed files with 217 additions and 19 deletions

View File

@@ -1,9 +1,9 @@
package ui
import (
"fmt"
"net/http"
"git.wntrmute.dev/kyle/mcias/internal/audit"
"git.wntrmute.dev/kyle/mcias/internal/auth"
"git.wntrmute.dev/kyle/mcias/internal/crypto"
"git.wntrmute.dev/kyle/mcias/internal/model"
@@ -59,7 +59,7 @@ func (u *UIServer) handleLoginPost(w http.ResponseWriter, r *http.Request) {
// Security: always run dummy Argon2 to prevent timing-based user enumeration.
_, _ = auth.VerifyPassword("dummy", u.dummyHash())
u.writeAudit(r, model.EventLoginFail, nil, nil,
fmt.Sprintf(`{"username":%q,"reason":"unknown_user"}`, username))
audit.JSON("username", username, "reason", "unknown_user"))
u.render(w, "login", LoginData{Error: "invalid credentials"})
return
}
@@ -132,7 +132,7 @@ func (u *UIServer) handleTOTPStep(w http.ResponseWriter, r *http.Request) {
accountID, ok := u.consumeTOTPNonce(nonce)
if !ok {
u.writeAudit(r, model.EventLoginFail, nil, nil,
fmt.Sprintf(`{"username":%q,"reason":"invalid_totp_nonce"}`, username))
audit.JSON("username", username, "reason", "invalid_totp_nonce"))
u.render(w, "login", LoginData{Error: "session expired, please log in again"})
return
}
@@ -240,7 +240,7 @@ func (u *UIServer) finishLogin(w http.ResponseWriter, r *http.Request, acct *mod
u.writeAudit(r, model.EventLoginOK, &acct.ID, nil, "")
u.writeAudit(r, model.EventTokenIssued, &acct.ID, nil,
fmt.Sprintf(`{"jti":%q,"via":"ui"}`, claims.JTI))
audit.JSON("jti", claims.JTI, "via", "ui"))
// Redirect to dashboard.
if isHTMX(r) {
@@ -261,7 +261,7 @@ func (u *UIServer) handleLogout(w http.ResponseWriter, r *http.Request) {
u.logger.Warn("revoke token on UI logout", "error", revokeErr)
}
u.writeAudit(r, model.EventTokenRevoked, nil, nil,
fmt.Sprintf(`{"jti":%q,"reason":"ui_logout"}`, claims.JTI))
audit.JSON("jti", claims.JTI, "reason", "ui_logout"))
}
}
u.clearSessionCookie(w)