csrf

package
v0.0.0-...-8e189b8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2025 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package csrf provides lightweight CSRF protection for Go net/http servers using the double-submit cookie pattern.

How it works

  • Safe methods (GET, HEAD, OPTIONS): ensure a CSRF token cookie exists and inject the token into the request context so handlers can read it via TokenFromContext.
  • Unsafe methods (POST, PUT, PATCH, DELETE): optionally enforce same-site policy using Origin/Referer (when EnforceOriginCheck is enabled) and then require the client-provided token (from header or form field) to match the token stored in the cookie. Comparison is done in constant time.

Configuration

All behavior is driven by Config. Key fields include:

  • CookieName, CookiePath, CookieDomain, CookieSecure, CookieHTTPOnly, CookieSameSite, CookieMaxAge
  • HeaderName (default: "X-CSRF-Token")
  • FormField (default: "csrf_token")
  • EnforceOriginCheck and AllowedOrigin (empty means use the request host)
  • TokenBytes (default: 32)

HttpOnly note By default many double-submit implementations keep HttpOnly=false so client code can read the token when necessary. If you do not need client-side reads (e.g., you fetch tokens via TokenHandler or inject them server-side), set CookieHTTPOnly=true.

Typical usage

p := csrf.New(csrf.Config{ EnforceOriginCheck: true })
// Protect an http.Handler (router, mux, etc.)
protected := p.Protect(appMux)
http.ListenAndServe(":8080", protected)

In handlers, you can read the token from context for rendering or APIs:

if tok, ok := csrf.TokenFromContext(r.Context()); ok {
    // use tok in templates or return it from an endpoint
}

For SPAs, expose a small endpoint that returns the current token:

r.Get("/csrf-token", func(w http.ResponseWriter, r *http.Request) {
    p.TokenHandler().ServeHTTP(w, r)
})

Repository <https://github.com/JeanGrijp/go-csrf>

README and Examples

Go Reference <https://pkg.go.dev/github.com/JeanGrijp/go-csrf/csrf>

Package csrf provides a lightweight double-submit-cookie CSRF protection middleware.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func TokenFromContext

func TokenFromContext(ctx context.Context) (string, bool)

TokenFromContext returns the CSRF token stored in ctx, if present.

Params: - ctx: context potentially containing a token set by the middleware.

Returns: - token (string) and a boolean indicating whether a token was found.

Types

type Config

type Config struct {
	// CookieName is the name of the CSRF token cookie.
	// Default: "csrf_token".
	CookieName string

	// CookiePath is the Path attribute for the CSRF cookie.
	// Default: "/".
	CookiePath string

	// CookieDomain is the Domain attribute for the CSRF cookie.
	// Leave empty to omit the attribute.
	CookieDomain string

	// CookieSecure controls the Secure flag of the CSRF cookie.
	// Should be true in production when using HTTPS.
	CookieSecure bool

	// CookieHTTPOnly controls the HttpOnly flag of the CSRF cookie.
	// Default: false (double-submit pattern commonly requires client-side read).
	// Set to true if you always fetch the token via TokenHandler or inject it server-side.
	CookieHTTPOnly bool

	// CookieSameSite sets the SameSite attribute of the CSRF cookie.
	// Default: http.SameSiteLaxMode.
	CookieSameSite http.SameSite

	// CookieMaxAge is the Max-Age attribute in seconds.
	// 0 means a session cookie (no Max-Age attribute). Negative values are not set by this package.
	CookieMaxAge int // in seconds

	// HeaderName is the HTTP header from which the client provides the token
	// on unsafe requests.
	// Default: "X-CSRF-Token".
	HeaderName string

	// FormField is the form field name (application/x-www-form-urlencoded or
	// multipart/form-data) from which the client may provide the token.
	// Default: "csrf_token".
	FormField string

	// EnforceOriginCheck, when true, validates that unsafe requests originate
	// from the same site by checking the Origin header or, if absent, the
	// Referer header.
	EnforceOriginCheck bool

	// AllowedOrigin is the allowed site (host) for same-site checks when
	// EnforceOriginCheck is enabled. If empty, the current request host (r.Host)
	// is used.
	// Example: "app.example.com"
	AllowedOrigin string

	// TokenBytes is the number of random bytes used to generate the token
	// before base64url encoding (no padding).
	// Default: 32.
	TokenBytes int
}

Config holds cookie attributes, token transport options and security flags used by the CSRF protector. New applies sensible defaults when fields are left empty/zero.

Notes

  • This middleware uses the double-submit cookie pattern, which requires the CSRF cookie to be readable by client-side code; therefore the cookie is set with HttpOnly=false by design.
  • Defaults applied by New when zero values are provided: CookieName="csrf_token", CookiePath="/", CookieSameSite=http.SameSiteLaxMode, HeaderName="X-CSRF-Token", FormField="csrf_token", TokenBytes=32.

type Protector

type Protector struct {
	// contains filtered or unexported fields
}

func New

func New(cfg Config) *Protector

New receives a Config (cfg) with cookie, transport and security settings, applies reasonable defaults when fields are empty, and returns a configured *Protector ready to be used as middleware. It never returns nil.

Params: - cfg: configuration values (cookie options, header/form names, security flags).

Returns: - *Protector with defaults applied.

func (*Protector) Protect

func (p *Protector) Protect(next http.Handler) http.Handler

Protect wraps the given next http.Handler and enforces CSRF protection.

Behavior:

  • For "safe" methods (GET/HEAD/OPTIONS): ensures the token cookie exists and injects the token into the request context, then calls next.
  • For "unsafe" methods (POST/PUT/PATCH/DELETE): optionally validates Origin/Referer (when EnforceOriginCheck is true), extracts the client token from header or form, compares it in constant time against the cookie token, and only then calls next.

Params: - next: downstream handler to be executed after CSRF checks pass.

Returns: - An http.Handler that performs the CSRF logic before delegating to next.

func (*Protector) TokenHandler

func (p *Protector) TokenHandler() http.Handler

TokenHandler returns an HTTP handler that writes the current CSRF token. This is useful for SPAs to fetch the token and attach it to subsequent requests.

Returns: - http.Handler that responds with the token in the response body (text/plain).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL