Harden auth: setup secret, throttling, session destroy, secure cookies.

Replace username-based admin bootstrap with a one-time setup secret, rate-limit login/register, equalize login bcrypt timing, cap passwords at 72 bytes, destroy sessions on logout, and require Secure cookies when PORT is set.
This commit is contained in:
2026-08-22 11:47:42 -07:00
parent 96b0ce795a
commit 59513ab75e
9 changed files with 287 additions and 50 deletions
+17 -3
View File
@@ -54,9 +54,10 @@ func openDB() (*sql.DB, *store.SessionStore) {
func newHandler(db *sql.DB, sessions *store.SessionStore, uploader blob.Uploader) http.Handler {
srv, err := web.New(store.NewPostgres(db), sessions.Store(), plumber.TemplateFS, plumber.StaticFS, web.Config{
AdminUsername: os.Getenv("ADMIN_USERNAME"),
SecureCookie: os.Getenv("SECURE_COOKIE") == "1",
Blob: uploader,
AdminSetupSecret: strings.TrimSpace(os.Getenv("ADMIN_SETUP_SECRET")),
SecureCookie: secureCookieFromEnv(),
TrustProxy: os.Getenv("TRUST_PROXY") == "1",
Blob: uploader,
})
if err != nil {
log.Fatalf("server: %v", err)
@@ -64,6 +65,19 @@ func newHandler(db *sql.DB, sessions *store.SessionStore, uploader blob.Uploader
return srv.Handler()
}
// secureCookieFromEnv defaults to secure when PORT is set (PaaS/production)
// and refuses an explicit disable in that environment.
func secureCookieFromEnv() bool {
v := strings.TrimSpace(os.Getenv("SECURE_COOKIE"))
if strings.TrimSpace(os.Getenv("PORT")) != "" {
if v == "0" {
log.Fatal("SECURE_COOKIE=0 is not allowed when PORT is set")
}
return true
}
return v == "1"
}
func run(httpSrv *http.Server) {
errCh := make(chan error, 1)
go func() {