package basicauth import ( "crypto/subtle" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/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 // Users defines the allowed credentials // // Required. Default: map[string]string{} Users map[string]string // Realm is a string to define realm attribute of BasicAuth. // the realm identifies the system to authenticate against // and can be used by clients to save credentials // // Optional. Default: "Restricted". Realm string // Authorizer defines a function you can pass // to check the credentials however you want. // It will be called with a username and password // and is expected to return true or false to indicate // that the credentials were approved or not. // // Optional. Default: nil. Authorizer func(string, string) bool // Unauthorized defines the response body for unauthorized responses. // By default it will return with a 401 Unauthorized and the correct WWW-Auth header // // Optional. Default: nil Unauthorized fiber.Handler // ContextUser is the key to store the username in Locals // // Optional. Default: "username" ContextUsername string // ContextPass is the key to store the password in Locals // // Optional. Default: "password" ContextPassword string } // ConfigDefault is the default config // //nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Users: map[string]string{}, Realm: "Restricted", Authorizer: nil, Unauthorized: nil, ContextUsername: "username", ContextPassword: "password", } // 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.Next == nil { cfg.Next = ConfigDefault.Next } if cfg.Users == nil { cfg.Users = ConfigDefault.Users } if cfg.Realm == "" { cfg.Realm = ConfigDefault.Realm } if cfg.Authorizer == nil { cfg.Authorizer = func(user, pass string) bool { userPwd, exist := cfg.Users[user] return exist && subtle.ConstantTimeCompare(utils.UnsafeBytes(userPwd), utils.UnsafeBytes(pass)) == 1 } } if cfg.Unauthorized == nil { cfg.Unauthorized = func(c *fiber.Ctx) error { c.Set(fiber.HeaderWWWAuthenticate, "basic realm="+cfg.Realm) return c.SendStatus(fiber.StatusUnauthorized) } } if cfg.ContextUsername == "" { cfg.ContextUsername = ConfigDefault.ContextUsername } if cfg.ContextPassword == "" { cfg.ContextPassword = ConfigDefault.ContextPassword } return cfg }