aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web/handlers_auth.go
diff options
context:
space:
mode:
authorgrm <grm@eyesin.space>2026-09-18 13:47:49 +0300
committergrm <grm@eyesin.space>2026-09-18 13:47:49 +0300
commit3eeaa6d9a33f9294ade64c8ff26144fba86a379e (patch)
tree1c4bf44884ea59f7e3d9ca12008846f08bf72d16 /internal/web/handlers_auth.go
parent254733b0566830a46e5a44c2d3127f57bfaceb65 (diff)
downloadblogspace-3eeaa6d9a33f9294ade64c8ff26144fba86a379e.tar.gz
blogspace-3eeaa6d9a33f9294ade64c8ff26144fba86a379e.tar.bz2
blogspace-3eeaa6d9a33f9294ade64c8ff26144fba86a379e.zip
Security: Add HTTPS and TRUST_PROXY settings
The app only ever speaks plain HTTP, so it could not know the site was served over TLS: generated links were http:// (the /webadmin bounce from a blog host sent the login page over http), the session cookie was never Secure and nothing sent HSTS. HTTPS=true fixes all three; ClearSessionCookie now uses the same attributes as the set, since a browser only replaces a cookie whose Secure flag matches. TRUST_PROXY=true makes the client address the last X-Forwarded-For entry — the one our proxy appended — so throttling and the log see real addresses instead of the proxy's; earlier entries are whatever the client sent and are ignored. Production startup warns when HTTPS is off. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'internal/web/handlers_auth.go')
-rw-r--r--internal/web/handlers_auth.go12
1 files changed, 6 insertions, 6 deletions
diff --git a/internal/web/handlers_auth.go b/internal/web/handlers_auth.go
index 69b7b98..6c76d81 100644
--- a/internal/web/handlers_auth.go
+++ b/internal/web/handlers_auth.go
@@ -63,7 +63,7 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
}
// Both buckets must have a token: one address guessing many accounts and
// many addresses guessing one account are throttled alike.
- if !s.throttle(w, r, s.loginLimit, "ip:"+clientIP(r)) || !s.throttle(w, r, s.loginLimit, "user:"+strings.ToLower(username)) {
+ if !s.throttle(w, r, s.loginLimit, "ip:"+s.clientIP(r)) || !s.throttle(w, r, s.loginLimit, "user:"+strings.ToLower(username)) {
return
}
u, err := s.st.UserByUsername(r.Context(), username)
@@ -73,12 +73,12 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
return
}
auth.CheckPassword("$2a$10$invalidinvalidinvalidinvalidinvalidinvalidinvalidinval", password) // constant-ish time
- logf("login failed for %q from %s", username, clientIP(r))
+ logf("login failed for %q from %s", username, s.clientIP(r))
fail()
return
}
if u.Disabled || !auth.CheckPassword(u.PasswordHash, password) {
- logf("login failed for %q from %s", username, clientIP(r))
+ logf("login failed for %q from %s", username, s.clientIP(r))
fail()
return
}
@@ -87,12 +87,12 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
s.serverError(w, err)
return
}
- auth.SetSessionCookie(w, tok)
+ auth.SetSessionCookie(w, tok, s.cfg.HTTPS)
http.Redirect(w, r, s.landing(r, u, next), http.StatusSeeOther)
}
func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
- auth.ClearSessionCookie(w)
+ auth.ClearSessionCookie(w, s.cfg.HTTPS)
http.Redirect(w, r, "/webadmin", http.StatusSeeOther)
}
@@ -149,7 +149,7 @@ func (s *Server) handlePassword(w http.ResponseWriter, r *http.Request) {
s.serverError(w, err)
return
}
- auth.SetSessionCookie(w, tok)
+ auth.SetSessionCookie(w, tok, s.cfg.HTTPS)
redirectOK(w, r, "/dashboard", s.tr(r, "Password changed."))
}