diff --git a/csrf.go b/csrf.go index a94be83..42f46d6 100644 --- a/csrf.go +++ b/csrf.go @@ -25,6 +25,7 @@ func setCSRFToken(w http.ResponseWriter) (string, error) { Path: "/", HttpOnly: false, // must be readable via form hidden field comparison SameSite: http.SameSiteStrictMode, + Secure: !devMode, }) return token, nil } diff --git a/main.go b/main.go index ec6e888..36ab61d 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ import ( ) var myPublicURL = "https://ldap.nemunai.re" +var devMode bool // dockerRegistrySecret is required for X-Special-Auth anonymous access. // If empty, the feature is disabled. @@ -80,9 +81,14 @@ func main() { var baseURL = flag.String("baseurl", "/", "URL prepended to each URL") var configfile = flag.String("config", "", "path to the configuration file") var publicURL = flag.String("public-url", myPublicURL, "Public base URL used in password reset emails") + var dev = flag.Bool("dev", false, "Development mode: disables HSTS and cookie Secure flag for local HTTP testing") flag.Parse() myPublicURL = *publicURL + devMode = *dev + if devMode { + log.Println("WARNING: running in development mode — security features relaxed, do not use in production") + } // Sanitize options log.Println("Checking paths...") diff --git a/static.go b/static.go index 6fd5ff6..4946083 100644 --- a/static.go +++ b/static.go @@ -13,7 +13,9 @@ func securityHeaders(next http.Handler) http.Handler { w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin") w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline' https://stackpath.bootstrapcdn.com; style-src https://stackpath.bootstrapcdn.com; img-src 'self'; font-src https://stackpath.bootstrapcdn.com") - w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains") + if !devMode { + w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains") + } next.ServeHTTP(w, r) }) }