web/csrf package provides two CSRF strategies: the session-backed
synchronizer token (default) and the double-submit cookie.
Import
How it works
The middleware decision tree — storage (synchronizer vs. double-submit) only changes where the token is loaded from, not this validation path: CSRF protection validates every request whose method is not inConfig.SafeMethods. The default safe methods are GET, HEAD, and
OPTIONS — TRACE is intentionally not safe: it can echo request
contents and is disabled on hardened servers, so the safer default is to treat
it as state-changing (a token is required).
On a safe-method request, the middleware ensures a token exists (generating
and persisting one if absent) and exposes it via csrf.TokenFrom(ctx) for
handlers/templates to render. On an unsafe-method request, it loads the
expected token, reads the actual token from the configured header then the
form param, and compares them with a constant-time check.
Synchronizer Token (default)
The token is stored as a session attribute (not a cookie) and is stable across requests untilRotate is called.
NewSynchronizerRepository(store session.Store, cookie session.CookieConfig) csrf.Repository
takes the same session.Store and session.CookieConfig used by the session
middleware, so it can locate the caller’s session. There is no XSRF-TOKEN
cookie written by this strategy — the token never leaves the session, so a
client that needs to read the token (e.g. an SPA) must get it from a page
render via csrf.TokenFrom, not from a cookie.
Double-Submit Cookie
Stateless alternative — no session required. The token is stored in a cookie and mirrored in theX-CSRF-Token header; the server compares the cookie
value to the echoed header/form value.
NewDoubleSubmitRepository(cookie session.CookieConfig) csrf.Repository
writes the CSRF cookie with HttpOnly: false (so client JavaScript can read
and echo it) but keeps Secure and SameSite=Lax. This is the only cookie in
the web layer permitted to be non-HttpOnly.
The double-submit cookie is not HMAC-signed — it relies on the
same-origin policy preventing another origin from reading or setting the
cookie, not on a secret. It is weaker than the synchronizer against
subdomain / cookie-injection attacks (an attacker who can set a cookie on a
sibling subdomain can forge both halves), so prefer the synchronizer whenever
a session exists.
SPA integration
Angular, React, and Vue all support reading a cookie and sending it as a header — this only applies to the double-submit strategy, since the synchronizer strategy never puts the token in a cookie. TheToken.HeaderName
this library expects defaults to X-CSRF-Token (there is no constructor
parameter to change it), so point your SPA’s client at that header name
rather than assuming a framework’s own default:
Disabling CSRF
CSRF can only be disabled for bearer-token-authenticated APIs where session cookies are never used:CSRFDisabled() with WithLogin() is a login-CSRF vulnerability. New()
errors on this pair unless you call AllowLoginWithoutCSRF() to confirm that
CSRF is enforced at another layer (e.g. an edge gateway).
Custom exemptions
To exempt specific paths from CSRF (e.g. a webhook endpoint), setConfig.Skip, a predicate over the request. securityhttp does not
currently expose Skip, so build the middleware directly with csrf.Middleware
when you need exemptions:
