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())How it works
Section titled “How it works”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-originornone— 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 a403error 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 },}))Token-based protection
Section titled “Token-based protection”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,})Accessing the CSRF token
Section titled “Accessing the CSRF token”- Server-side — the token is available from the context under
ContextKeyand can be passed to the client via a template. - Client-side — the token can be read from the CSRF cookie.
Configuration
Section titled “Configuration”CSRFConfig · github.com/labstack/echo/v5@5196b9b
| Field | Type | Description | Source |
|---|---|---|---|
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 |
Default configuration
Section titled “Default configuration”var DefaultCSRFConfig = CSRFConfig{ Skipper: DefaultSkipper, TokenLength: 32, TokenLookup: "header:" + echo.HeaderXCSRFToken, ContextKey: "csrf", CookieName: "_csrf", CookieMaxAge: 86400, CookieSameSite: http.SameSiteDefaultMode,}Full example
Section titled “Full example”A complete, runnable example is available in the echox cookbook.