github.com/gofiber/fiber/v2@v2.47.0/middleware/csrf/config.go (about)

     1  package csrf
     2  
     3  import (
     4  	"log"
     5  	"net/textproto"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/gofiber/fiber/v2"
    10  	"github.com/gofiber/fiber/v2/utils"
    11  )
    12  
    13  // Config defines the config for middleware.
    14  type Config struct {
    15  	// Next defines a function to skip this middleware when returned true.
    16  	//
    17  	// Optional. Default: nil
    18  	Next func(c *fiber.Ctx) bool
    19  
    20  	// KeyLookup is a string in the form of "<source>:<key>" that is used
    21  	// to create an Extractor that extracts the token from the request.
    22  	// Possible values:
    23  	// - "header:<name>"
    24  	// - "query:<name>"
    25  	// - "param:<name>"
    26  	// - "form:<name>"
    27  	// - "cookie:<name>"
    28  	//
    29  	// Ignored if an Extractor is explicitly set.
    30  	//
    31  	// Optional. Default: "header:X-CSRF-Token"
    32  	KeyLookup string
    33  
    34  	// Name of the session cookie. This cookie will store session key.
    35  	// Optional. Default value "csrf_".
    36  	CookieName string
    37  
    38  	// Domain of the CSRF cookie.
    39  	// Optional. Default value "".
    40  	CookieDomain string
    41  
    42  	// Path of the CSRF cookie.
    43  	// Optional. Default value "".
    44  	CookiePath string
    45  
    46  	// Indicates if CSRF cookie is secure.
    47  	// Optional. Default value false.
    48  	CookieSecure bool
    49  
    50  	// Indicates if CSRF cookie is HTTP only.
    51  	// Optional. Default value false.
    52  	CookieHTTPOnly bool
    53  
    54  	// Value of SameSite cookie.
    55  	// Optional. Default value "Lax".
    56  	CookieSameSite string
    57  
    58  	// Decides whether cookie should last for only the browser sesison.
    59  	// Ignores Expiration if set to true
    60  	CookieSessionOnly bool
    61  
    62  	// Expiration is the duration before csrf token will expire
    63  	//
    64  	// Optional. Default: 1 * time.Hour
    65  	Expiration time.Duration
    66  
    67  	// Store is used to store the state of the middleware
    68  	//
    69  	// Optional. Default: memory.New()
    70  	Storage fiber.Storage
    71  
    72  	// Context key to store generated CSRF token into context.
    73  	// If left empty, token will not be stored in context.
    74  	//
    75  	// Optional. Default: ""
    76  	ContextKey string
    77  
    78  	// KeyGenerator creates a new CSRF token
    79  	//
    80  	// Optional. Default: utils.UUID
    81  	KeyGenerator func() string
    82  
    83  	// Deprecated: Please use Expiration
    84  	CookieExpires time.Duration
    85  
    86  	// Deprecated: Please use Cookie* related fields
    87  	Cookie *fiber.Cookie
    88  
    89  	// Deprecated: Please use KeyLookup
    90  	TokenLookup string
    91  
    92  	// ErrorHandler is executed when an error is returned from fiber.Handler.
    93  	//
    94  	// Optional. Default: DefaultErrorHandler
    95  	ErrorHandler fiber.ErrorHandler
    96  
    97  	// Extractor returns the csrf token
    98  	//
    99  	// If set this will be used in place of an Extractor based on KeyLookup.
   100  	//
   101  	// Optional. Default will create an Extractor based on KeyLookup.
   102  	Extractor func(c *fiber.Ctx) (string, error)
   103  }
   104  
   105  const HeaderName = "X-Csrf-Token"
   106  
   107  // ConfigDefault is the default config
   108  var ConfigDefault = Config{
   109  	KeyLookup:      "header:" + HeaderName,
   110  	CookieName:     "csrf_",
   111  	CookieSameSite: "Lax",
   112  	Expiration:     1 * time.Hour,
   113  	KeyGenerator:   utils.UUID,
   114  	ErrorHandler:   defaultErrorHandler,
   115  	Extractor:      CsrfFromHeader(HeaderName),
   116  }
   117  
   118  // default ErrorHandler that process return error from fiber.Handler
   119  func defaultErrorHandler(_ *fiber.Ctx, _ error) error {
   120  	return fiber.ErrForbidden
   121  }
   122  
   123  // Helper function to set default values
   124  func configDefault(config ...Config) Config {
   125  	// Return default config if nothing provided
   126  	if len(config) < 1 {
   127  		return ConfigDefault
   128  	}
   129  
   130  	// Override default config
   131  	cfg := config[0]
   132  
   133  	// Set default values
   134  	if cfg.TokenLookup != "" {
   135  		log.Printf("[Warning] - [CSRF] TokenLookup is deprecated, please use KeyLookup\n")
   136  		cfg.KeyLookup = cfg.TokenLookup
   137  	}
   138  	if int(cfg.CookieExpires.Seconds()) > 0 {
   139  		log.Printf("[Warning] - [CSRF] CookieExpires is deprecated, please use Expiration\n")
   140  		cfg.Expiration = cfg.CookieExpires
   141  	}
   142  	if cfg.Cookie != nil {
   143  		log.Printf("[Warning] - [CSRF] Cookie is deprecated, please use Cookie* related fields\n")
   144  		if cfg.Cookie.Name != "" {
   145  			cfg.CookieName = cfg.Cookie.Name
   146  		}
   147  		if cfg.Cookie.Domain != "" {
   148  			cfg.CookieDomain = cfg.Cookie.Domain
   149  		}
   150  		if cfg.Cookie.Path != "" {
   151  			cfg.CookiePath = cfg.Cookie.Path
   152  		}
   153  		cfg.CookieSecure = cfg.Cookie.Secure
   154  		cfg.CookieHTTPOnly = cfg.Cookie.HTTPOnly
   155  		if cfg.Cookie.SameSite != "" {
   156  			cfg.CookieSameSite = cfg.Cookie.SameSite
   157  		}
   158  	}
   159  	if cfg.KeyLookup == "" {
   160  		cfg.KeyLookup = ConfigDefault.KeyLookup
   161  	}
   162  	if int(cfg.Expiration.Seconds()) <= 0 {
   163  		cfg.Expiration = ConfigDefault.Expiration
   164  	}
   165  	if cfg.CookieName == "" {
   166  		cfg.CookieName = ConfigDefault.CookieName
   167  	}
   168  	if cfg.CookieSameSite == "" {
   169  		cfg.CookieSameSite = ConfigDefault.CookieSameSite
   170  	}
   171  	if cfg.KeyGenerator == nil {
   172  		cfg.KeyGenerator = ConfigDefault.KeyGenerator
   173  	}
   174  	if cfg.ErrorHandler == nil {
   175  		cfg.ErrorHandler = ConfigDefault.ErrorHandler
   176  	}
   177  
   178  	// Generate the correct extractor to get the token from the correct location
   179  	selectors := strings.Split(cfg.KeyLookup, ":")
   180  
   181  	const numParts = 2
   182  	if len(selectors) != numParts {
   183  		panic("[CSRF] KeyLookup must in the form of <source>:<key>")
   184  	}
   185  
   186  	if cfg.Extractor == nil {
   187  		// By default we extract from a header
   188  		cfg.Extractor = CsrfFromHeader(textproto.CanonicalMIMEHeaderKey(selectors[1]))
   189  
   190  		switch selectors[0] {
   191  		case "form":
   192  			cfg.Extractor = CsrfFromForm(selectors[1])
   193  		case "query":
   194  			cfg.Extractor = CsrfFromQuery(selectors[1])
   195  		case "param":
   196  			cfg.Extractor = CsrfFromParam(selectors[1])
   197  		case "cookie":
   198  			cfg.Extractor = CsrfFromCookie(selectors[1])
   199  		}
   200  	}
   201  
   202  	return cfg
   203  }