aboutsummaryrefslogtreecommitdiffstats
path: root/internal/auth/cookie.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/auth/cookie.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/auth/cookie.go')
-rw-r--r--internal/auth/cookie.go27
1 files changed, 18 insertions, 9 deletions
diff --git a/internal/auth/cookie.go b/internal/auth/cookie.go
index 9fd6b6e..8fa394d 100644
--- a/internal/auth/cookie.go
+++ b/internal/auth/cookie.go
@@ -7,17 +7,26 @@ import (
const CookieName = "session"
-func SetSessionCookie(w http.ResponseWriter, token string) {
- http.SetCookie(w, &http.Cookie{
+// SetSessionCookie sets the session cookie; secure marks it for https only,
+// which the app cannot tell on its own behind a plain-http proxy.
+func SetSessionCookie(w http.ResponseWriter, token string, secure bool) {
+ http.SetCookie(w, sessionCookie(token, int(SessionTTL/time.Second), secure))
+}
+
+// ClearSessionCookie expires the cookie with the same attributes it was set
+// with; browsers only replace a cookie whose Secure flag matches.
+func ClearSessionCookie(w http.ResponseWriter, secure bool) {
+ http.SetCookie(w, sessionCookie("", -1, secure))
+}
+
+func sessionCookie(value string, maxAge int, secure bool) *http.Cookie {
+ return &http.Cookie{
Name: CookieName,
- Value: token,
+ Value: value,
Path: "/",
HttpOnly: true,
+ Secure: secure,
SameSite: http.SameSiteLaxMode,
- MaxAge: int(SessionTTL / time.Second),
- })
-}
-
-func ClearSessionCookie(w http.ResponseWriter) {
- http.SetCookie(w, &http.Cookie{Name: CookieName, Value: "", Path: "/", HttpOnly: true, MaxAge: -1})
+ MaxAge: maxAge,
+ }
}