github.com/gofiber/fiber/v2@v2.47.0/middleware/csrf/csrf.go (about) 1 package csrf 2 3 import ( 4 "errors" 5 "time" 6 7 "github.com/gofiber/fiber/v2" 8 ) 9 10 var errTokenNotFound = errors.New("csrf token not found") 11 12 // New creates a new middleware handler 13 func New(config ...Config) fiber.Handler { 14 // Set default config 15 cfg := configDefault(config...) 16 17 // Create manager to simplify storage operations ( see manager.go ) 18 manager := newManager(cfg.Storage) 19 20 dummyValue := []byte{'+'} 21 22 // Return new handler 23 return func(c *fiber.Ctx) error { 24 // Don't execute middleware if Next returns true 25 if cfg.Next != nil && cfg.Next(c) { 26 return c.Next() 27 } 28 29 var token string 30 31 // Action depends on the HTTP method 32 switch c.Method() { 33 case fiber.MethodGet, fiber.MethodHead, fiber.MethodOptions, fiber.MethodTrace: 34 // Declare empty token and try to get existing CSRF from cookie 35 token = c.Cookies(cfg.CookieName) 36 default: 37 // Assume that anything not defined as 'safe' by RFC7231 needs protection 38 39 // Extract token from client request i.e. header, query, param, form or cookie 40 token, err := cfg.Extractor(c) 41 if err != nil { 42 return cfg.ErrorHandler(c, err) 43 } 44 45 // if token does not exist in Storage 46 if manager.getRaw(token) == nil { 47 // Expire cookie 48 c.Cookie(&fiber.Cookie{ 49 Name: cfg.CookieName, 50 Domain: cfg.CookieDomain, 51 Path: cfg.CookiePath, 52 Expires: time.Now().Add(-1 * time.Minute), 53 Secure: cfg.CookieSecure, 54 HTTPOnly: cfg.CookieHTTPOnly, 55 SameSite: cfg.CookieSameSite, 56 SessionOnly: cfg.CookieSessionOnly, 57 }) 58 return cfg.ErrorHandler(c, errTokenNotFound) 59 } 60 } 61 62 // Generate CSRF token if not exist 63 if token == "" { 64 // And generate a new token 65 token = cfg.KeyGenerator() 66 } 67 68 // Add/update token to Storage 69 manager.setRaw(token, dummyValue, cfg.Expiration) 70 71 // Create cookie to pass token to client 72 cookie := &fiber.Cookie{ 73 Name: cfg.CookieName, 74 Value: token, 75 Domain: cfg.CookieDomain, 76 Path: cfg.CookiePath, 77 Expires: time.Now().Add(cfg.Expiration), 78 Secure: cfg.CookieSecure, 79 HTTPOnly: cfg.CookieHTTPOnly, 80 SameSite: cfg.CookieSameSite, 81 SessionOnly: cfg.CookieSessionOnly, 82 } 83 // Set cookie to response 84 c.Cookie(cookie) 85 86 // Protect clients from caching the response by telling the browser 87 // a new header value is generated 88 c.Vary(fiber.HeaderCookie) 89 90 // Store token in context if set 91 if cfg.ContextKey != "" { 92 c.Locals(cfg.ContextKey, token) 93 } 94 95 // Continue stack 96 return c.Next() 97 } 98 }