check / check (push) Canceled after 0s
seal.DeriveKeys derives the session hash and block keys, the encrypted URL key and the CSRF key from the signing key, with their salts declared beside it, and returns them as one seal.Keys. internal/providers calls it once at startup and provides the value to the fx graph. The session manager, the encrypted URL generator and the CSRF protection each take their own key. session.NewManager, encurl.NewGenerator, newCSRFProtect and handlers.New return no error, as nothing in them can fail now. Each key is derived as before, with seal.DeriveKey and the same salt. The signing key itself stays the HMAC key of signed URLs and the login password. README.md says under signing_key what it protects. Model: opus-5-5
56 lines
1.6 KiB
Go
56 lines
1.6 KiB
Go
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)
|
|
}
|