github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/http/fast/middleware/basicauth/basicauth.go (about) 1 package basicauth 2 3 import ( 4 "encoding/base64" 5 "github.com/angenalZZZ/gofunc/http/fast" 6 "strings" 7 ) 8 9 // Config defines the config for BasicAuth middleware 10 type Config struct { 11 // Filter defines a function to skip middleware. 12 // Optional. Default: nil 13 Filter func(*fast.Ctx) bool 14 // Users defines the allowed credentials 15 // Required. Default: map[string]string{} 16 Users map[string]string 17 // Realm is a string to define realm attribute of BasicAuth. 18 // the realm identifies the system to authenticate against 19 // and can be used by clients to save credentials 20 // Optional. Default: "Restricted". 21 Realm string 22 // Authorize defines a function you can pass 23 // to check the credentials however you want. 24 // It will be called with a username and password 25 // and is expected to return true or false to indicate 26 // that the credentials were approved or not. 27 // Optional. Default: nil. 28 Authorize func(string, string) bool 29 // Unauthorized defines the response body for unauthorized responses. 30 // Optional. Default: nil 31 Unauthorized func(*fast.Ctx) 32 } 33 34 // New middleware. 35 // cfg := basicauth.Config{ 36 // Users: map[string]string{ 37 // "admin": "123456", 38 // }, 39 // } 40 // app.Use(basicauth.New(cfg)) 41 func New(config ...Config) func(*fast.Ctx) { 42 // Init config 43 var cfg Config 44 if len(config) > 0 { 45 cfg = config[0] 46 } 47 if cfg.Users == nil { 48 cfg.Users = map[string]string{} 49 } 50 if cfg.Realm == "" { 51 cfg.Realm = "Restricted" 52 } 53 if cfg.Authorize == nil { 54 cfg.Authorize = func(user, pass string) bool { 55 if user == "" || pass == "" { 56 return false 57 } 58 if _pass, ok := cfg.Users[user]; ok { 59 return _pass == pass 60 } 61 return false 62 } 63 } 64 if cfg.Unauthorized == nil { 65 cfg.Unauthorized = func(c *fast.Ctx) { 66 c.SetHeader("WWW-Authenticate", "basic realm="+cfg.Realm) 67 c.SendStatus(401) 68 } 69 } 70 // Return middleware handler 71 return func(c *fast.Ctx) { 72 // Filter request to skip middleware 73 if cfg.Filter != nil && cfg.Filter(c) { 74 c.Next() 75 return 76 } 77 // GetHeader authorization header 78 auth := c.GetHeader("Authorization") 79 // Check if header is valid 80 if len(auth) > 6 && strings.ToLower(auth[:5]) == "basic" { 81 // Try to decode 82 if raw, err := base64.StdEncoding.DecodeString(auth[6:]); err == nil { 83 // Convert to string 84 cred := string(raw) 85 // Find semi column 86 for i := 0; i < len(cred); i++ { 87 if cred[i] == ':' { 88 // Split into user & pass 89 user := cred[:i] 90 pass := cred[i+1:] 91 // If exist & match in Users, we let him pass 92 if cfg.Authorize(user, pass) { 93 c.Next() 94 return 95 } 96 } 97 } 98 } 99 } 100 // Authentication failed 101 cfg.Unauthorized(c) 102 } 103 }