fiber/middleware/csrf/config.go
M. Efe Çetin a458bd344c
v3 (feature): convert fiber.Ctx type to interface (#1928)
*  v3: convert fiber.Ctx type to interface

* update ctx methods

* add new methods to customize ctx, fix some problems

* update comments.

* fix something
2022-07-13 07:48:29 +02:00

158 lines
3.9 KiB
Go

package csrf
import (
"net/textproto"
"strings"
"time"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/utils"
)
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip this middleware when returned true.
//
// Optional. Default: nil
Next func(c fiber.Ctx) bool
// KeyLookup is a string in the form of "<source>:<key>" that is used
// to extract token from the request.
// Possible values:
// - "header:<name>"
// - "query:<name>"
// - "param:<name>"
// - "form:<name>"
// - "cookie:<name>"
//
// Optional. Default: "header:X-CSRF-Token"
KeyLookup string
// Name of the session cookie. This cookie will store session key.
// Optional. Default value "csrf_".
CookieName string
// Domain of the CSRF cookie.
// Optional. Default value "".
CookieDomain string
// Path of the CSRF cookie.
// Optional. Default value "".
CookiePath string
// Indicates if CSRF cookie is secure.
// Optional. Default value false.
CookieSecure bool
// Indicates if CSRF cookie is HTTP only.
// Optional. Default value false.
CookieHTTPOnly bool
// Value of SameSite cookie.
// Optional. Default value "Lax".
CookieSameSite string
// Decides whether cookie should last for only the browser sesison.
// Ignores Expiration if set to true
CookieSessionOnly bool
// Expiration is the duration before csrf token will expire
//
// Optional. Default: 1 * time.Hour
Expiration time.Duration
// Store is used to store the state of the middleware
//
// Optional. Default: memory.New()
Storage fiber.Storage
// Context key to store generated CSRF token into context.
// If left empty, token will not be stored in context.
//
// Optional. Default: ""
ContextKey string
// KeyGenerator creates a new CSRF token
//
// Optional. Default: utils.UUID
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 based on KeyLookup
extractor func(c fiber.Ctx) (string, error)
}
// ConfigDefault is the default config
var ConfigDefault = Config{
KeyLookup: "header:X-Csrf-Token",
CookieName: "csrf_",
CookieSameSite: "Lax",
Expiration: 1 * time.Hour,
KeyGenerator: utils.UUID,
ErrorHandler: defaultErrorHandler,
extractor: csrfFromHeader("X-Csrf-Token"),
}
// default ErrorHandler that process return error from fiber.Handler
var defaultErrorHandler = func(c fiber.Ctx, err error) error {
return fiber.ErrForbidden
}
// 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.KeyLookup == "" {
cfg.KeyLookup = ConfigDefault.KeyLookup
}
if int(cfg.Expiration.Seconds()) <= 0 {
cfg.Expiration = ConfigDefault.Expiration
}
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
}
// Generate the correct extractor to get the token from the correct location
selectors := strings.Split(cfg.KeyLookup, ":")
if len(selectors) != 2 {
panic("[CSRF] KeyLookup must in the form of <source>:<key>")
}
// By default we extract from a header
cfg.extractor = csrfFromHeader(textproto.CanonicalMIMEHeaderKey(selectors[1]))
switch selectors[0] {
case "form":
cfg.extractor = csrfFromForm(selectors[1])
case "query":
cfg.extractor = csrfFromQuery(selectors[1])
case "param":
cfg.extractor = csrfFromParam(selectors[1])
case "cookie":
cfg.extractor = csrfFromCookie(selectors[1])
}
return cfg
}