fiber/middleware/csrf/config.go
Jason McNeil e17bab7946
Refactor CSRF middleware and enhance documentation (#3598)
Co-authored-by: RW <rene@gofiber.io>
2025-07-19 20:11:33 +02:00

161 lines
4.3 KiB
Go

package csrf
import (
"time"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/session"
"github.com/gofiber/utils/v2"
)
// Config defines the config for CSRF middleware.
type Config struct {
// Storage is used to store the state of the middleware.
//
// Optional. Default: memory.New()
// Ignored if Session is set.
Storage fiber.Storage
// Next defines a function to skip this middleware when returned true.
//
// Optional. Default: nil
Next func(c fiber.Ctx) bool
// Session is used to store the state of the middleware.
//
// Optional. Default: nil
// If set, the middleware will use the session store instead of the storage.
Session *session.Store
// KeyGenerator creates a new CSRF token.
//
// Optional. Default: utils.UUIDv4
KeyGenerator func() string
// ErrorHandler is executed when an error is returned from fiber.Handler.
//
// Optional. Default: defaultErrorHandler
ErrorHandler fiber.ErrorHandler
// Extractor returns the CSRF token from the request.
//
// Optional. Default: FromHeader("X-Csrf-Token")
//
// Available extractors: FromHeader, FromQuery, FromParam, FromForm
//
// WARNING: Never create custom extractors that read from cookies with the same
// CookieName as this defeats CSRF protection entirely.
Extractor func(c fiber.Ctx) (string, error)
// CookieName is the name of the CSRF cookie.
//
// Optional. Default: "csrf_"
CookieName string
// CookieDomain is the domain of the CSRF cookie.
//
// Optional. Default: ""
CookieDomain string
// CookiePath is the path of the CSRF cookie.
//
// Optional. Default: ""
CookiePath string
// CookieSameSite is the SameSite attribute of the CSRF cookie.
//
// Optional. Default: "Lax"
CookieSameSite string
// TrustedOrigins is a list of trusted origins for unsafe requests.
// For requests that use the Origin header, the origin must match the
// Host header or one of the TrustedOrigins.
// For secure requests that do not include the Origin header, the Referer
// header must match the Host header or one of the TrustedOrigins.
//
// This supports matching subdomains at any level. This means you can use a value like
// "https://*.example.com" to allow any subdomain of example.com to submit requests,
// including multiple subdomain levels such as "https://sub.sub.example.com".
//
// Optional. Default: []
TrustedOrigins []string
// IdleTimeout is the duration of time the CSRF token is valid.
//
// Optional. Default: 30 * time.Minute
IdleTimeout time.Duration
// CookieSecure indicates if CSRF cookie is secure.
//
// Optional. Default: false
CookieSecure bool
// CookieHTTPOnly indicates if CSRF cookie is HTTP only.
//
// Optional. Default: false
CookieHTTPOnly bool
// CookieSessionOnly decides whether cookie should last for only the browser session.
// Ignores Expiration if set to true.
//
// Optional. Default: false
CookieSessionOnly bool
// SingleUseToken indicates if the CSRF token should be destroyed
// and a new one generated on each use.
//
// Optional. Default: false
SingleUseToken bool
}
// HeaderName is the default header name for CSRF tokens.
const HeaderName = "X-Csrf-Token"
// ConfigDefault is the default config for CSRF middleware.
var ConfigDefault = Config{
CookieName: "csrf_",
CookieSameSite: "Lax",
IdleTimeout: 30 * time.Minute,
KeyGenerator: utils.UUIDv4,
ErrorHandler: defaultErrorHandler,
Extractor: FromHeader(HeaderName),
}
// defaultErrorHandler is the default error handler that processes errors from fiber.Handler.
func defaultErrorHandler(_ fiber.Ctx, _ error) error {
return fiber.ErrForbidden
}
// configDefault is a helper function to set default values.
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return ConfigDefault
}
// Override default config
cfg := config[0]
// Set default values
if cfg.IdleTimeout <= 0 {
cfg.IdleTimeout = ConfigDefault.IdleTimeout
}
if cfg.CookieName == "" {
cfg.CookieName = ConfigDefault.CookieName
}
if cfg.CookieSameSite == "" {
cfg.CookieSameSite = ConfigDefault.CookieSameSite
}
if cfg.KeyGenerator == nil {
cfg.KeyGenerator = ConfigDefault.KeyGenerator
}
if cfg.ErrorHandler == nil {
cfg.ErrorHandler = ConfigDefault.ErrorHandler
}
if cfg.Extractor == nil {
cfg.Extractor = ConfigDefault.Extractor
}
return cfg
}