Skip to content

CSRF

Cross-Site Request Forgery (CSRF, sometimes pronounced “sea-surf”, or XSRF) is a type of malicious exploit where unauthorized commands are transmitted from a user that a website trusts.

All core middleware lives in the middleware package:

import "github.com/labstack/echo/v5/middleware"
e.Use(middleware.CSRF())

The CSRF middleware supports the Sec-Fetch-Site header as a modern, defense-in-depth approach to CSRF protection, implementing the OWASP-recommended Fetch Metadata API alongside the traditional token-based mechanism.

Modern browsers automatically send the Sec-Fetch-Site header with every request, indicating the relationship between the request origin and the target. The middleware uses this to make a security decision:

  • same-origin or none — allowed (exact origin match or direct user navigation)
  • same-site — falls back to token validation (for example, subdomain to main domain)
  • cross-site — blocked by default with a 403 error for unsafe methods (POST, PUT, DELETE, PATCH)

For browsers that do not send this header (older browsers), the middleware seamlessly falls back to traditional token-based CSRF protection.

Two options tune Sec-Fetch-Site behavior:

  • TrustedOrigins []string — allowlist specific origins for cross-site requests (useful for OAuth callbacks, webhooks)
  • AllowSecFetchSiteFunc func(c *echo.Context) (bool, error) — custom logic for same-site/cross-site validation
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
// Allow OAuth callbacks from a trusted provider.
TrustedOrigins: []string{"https://oauth-provider.com"},
// Custom validation for same-site/cross-site requests.
AllowSecFetchSiteFunc: func(c *echo.Context) (bool, error) {
// Your custom authorization logic here.
return validateCustomAuth(c), nil
// return true, err // blocks the request with an error
// return true, nil // allows the request through
// return false, nil // falls back to legacy token logic
},
}))
e := echo.New()
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
TokenLookup: "header:X-XSRF-TOKEN",
}))

The example above extracts the CSRF token from the X-XSRF-TOKEN request header.

Reading the token from a cookie instead:

middleware.CSRFWithConfig(middleware.CSRFConfig{
TokenLookup: "cookie:_csrf",
CookiePath: "/",
CookieDomain: "example.com",
CookieSecure: true,
CookieHTTPOnly: true,
CookieSameSite: http.SameSiteStrictMode,
})
  • Server-side — the token is available from the context under ContextKey and can be passed to the client via a template.
  • Client-side — the token can be read from the CSRF cookie.

CSRFConfig · github.com/labstack/echo/v5@fc41009

Fields from package source
FieldTypeDescriptionSource
Skipper Skipper Skipper defines a function to skip middleware. L29
TrustedOrigins []string TrustedOrigins permits any request with `Sec-Fetch-Site` header whose `Origin` header exactly matches a configured origin. Values should be formatted as Origin header "scheme://host[:port]". See [Origin]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin See [Sec-Fetch-Site]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#fetch-metadata-headers L36
AllowSecFetchSiteFunc func(c *echo.Context) (bool, error) AllowSecFetchSiteFunc allows custom behaviour for `Sec-Fetch-Site` requests that are about to fail with CSRF error, to be allowed or replaced with custom error. This function applies to `Sec-Fetch-Site` values: - `same-site` same registrable domain (subdomain and/or different port) - `cross-site` request originates from different site See [Sec-Fetch-Site]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#fetch-metadata-headers L44
TokenLength uint8 TokenLength is the length of the generated token. L47
TokenLookup string TokenLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used to extract token from the request. Optional. Default value "header:X-CSRF-Token". Possible values: - "header:<name>" or "header:<name>:<cut-prefix>" - "query:<name>" - "form:<name>" Multiple sources example: - "header:X-CSRF-Token,query:csrf" L59
Generator func() string Generator defines a function to generate token. Optional. Defaults to randomString(TokenLength). L63
ContextKey string Context key to store generated CSRF token into context. Optional. Default value "csrf". L67
CookieName string Name of the CSRF cookie. This cookie will store CSRF token. Optional. Default value "csrf". L71
CookieDomain string Domain of the CSRF cookie. Optional. Default value none. L75
CookiePath string Path of the CSRF cookie. Optional. Default value none. L79
CookieMaxAge int Max age (in seconds) of the CSRF cookie. Optional. Default value 86400 (24hr). L83
CookieSecure bool Indicates if CSRF cookie is secure. Optional. Default value false. L87
CookieHTTPOnly bool Indicates if CSRF cookie is HTTP only. Optional. Default value false. L91
CookieSameSite http.SameSite Indicates SameSite mode of the CSRF cookie. Optional. Default value SameSiteDefaultMode. L95
ErrorHandler func(c *echo.Context, err error) error ErrorHandler defines a function which is executed for returning custom errors. L98
Functions from package source
TypeSource
func CSRF() echo.MiddlewareFunc L117
func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc L122
var DefaultCSRFConfig = CSRFConfig{
Skipper: DefaultSkipper,
TokenLength: 32,
TokenLookup: "header:" + echo.HeaderXCSRFToken,
ContextKey: "csrf",
CookieName: "_csrf",
CookieMaxAge: 86400,
CookieSameSite: http.SameSiteDefaultMode,
}

A complete, runnable example is available in the echox cookbook.