package handlers import ( "html/template" "net/http" "github.com/gorilla/csrf" "sneak.berlin/go/pixa/internal/seal" ) // newCSRFProtect builds the CSRF-protection middleware for the // state-mutating HTML form routes. The token lives in its own cookie, // independent of the session cookie, so it also protects the login POST // where no session exists yet (login CSRF). key signs that cookie. // // When plaintext is true (local HTTP development), requests are marked // plaintext so the library neither demands an https Referer nor sets a // Secure cookie the browser would withhold over http. In production the // service runs behind a TLS-terminating proxy, so plaintext is false and // the library enforces its https Referer origin check. func newCSRFProtect( key [seal.KeySize]byte, plaintext bool, ) func(http.Handler) http.Handler { protect := csrf.Protect( key[:], csrf.Path("/"), csrf.Secure(!plaintext), csrf.SameSite(csrf.SameSiteStrictMode), ) if !plaintext { return protect } return func(next http.Handler) http.Handler { protected := protect(next) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { protected.ServeHTTP(w, csrf.PlaintextHTTPRequest(r)) }) } } // CSRF returns the CSRF-protection middleware for the login and generator // form routes. func (s *Handlers) CSRF() func(http.Handler) http.Handler { return s.csrfProtect } // csrfField returns the hidden form input carrying the CSRF token for the // given request, to be embedded verbatim in a rendered form. func csrfField(r *http.Request) template.HTML { return csrf.TemplateField(r) }