ToMiddleware converts BasicAuthConfig to middleware or returns an error for invalid configuration
()
| 95 | |
| 96 | // ToMiddleware converts BasicAuthConfig to middleware or returns an error for invalid configuration |
| 97 | func (config BasicAuthConfig) ToMiddleware() (echo.MiddlewareFunc, error) { |
| 98 | if config.Validator == nil { |
| 99 | return nil, errors.New("echo basic-auth middleware requires a validator function") |
| 100 | } |
| 101 | if config.Skipper == nil { |
| 102 | config.Skipper = DefaultSkipper |
| 103 | } |
| 104 | realm := defaultRealm |
| 105 | if config.Realm != "" { |
| 106 | realm = config.Realm |
| 107 | } |
| 108 | realm = strconv.Quote(realm) |
| 109 | limit := cmp.Or(config.AllowedCheckLimit, 1) |
| 110 | |
| 111 | return func(next echo.HandlerFunc) echo.HandlerFunc { |
| 112 | return func(c *echo.Context) error { |
| 113 | if config.Skipper(c) { |
| 114 | return next(c) |
| 115 | } |
| 116 | |
| 117 | var lastError error |
| 118 | l := len(basic) |
| 119 | i := uint(0) |
| 120 | for _, auth := range c.Request().Header[echo.HeaderAuthorization] { |
| 121 | if i >= limit { |
| 122 | break |
| 123 | } |
| 124 | if len(auth) <= l+1 || !strings.EqualFold(auth[:l], basic) { |
| 125 | continue |
| 126 | } |
| 127 | i++ |
| 128 | |
| 129 | // Invalid base64 shouldn't be treated as error |
| 130 | // instead should be treated as invalid client input |
| 131 | b, errDecode := base64.StdEncoding.DecodeString(auth[l+1:]) |
| 132 | if errDecode != nil { |
| 133 | lastError = echo.ErrBadRequest.Wrap(errDecode) |
| 134 | continue |
| 135 | } |
| 136 | before, after, ok := bytes.Cut(b, []byte{':'}) |
| 137 | if ok { |
| 138 | valid, errValidate := config.Validator(c, string(before), string(after)) |
| 139 | if errValidate != nil { |
| 140 | lastError = errValidate |
| 141 | } else if valid { |
| 142 | return next(c) |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | if lastError != nil { |
| 148 | return lastError |
| 149 | } |
| 150 | |
| 151 | // Need to return `401` for browsers to pop-up login box. |
| 152 | c.Response().Header().Set(echo.HeaderWWWAuthenticate, basic+" realm="+realm) |
| 153 | return echo.ErrUnauthorized |
| 154 | } |