/
basic-auth.go
99 lines (84 loc) · 3.39 KB
/
basic-auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package authentication
import (
"fmt"
"net/http"
"github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/authx/models"
"github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/config"
"github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/log"
responsehandler "github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/response-handler"
"github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/server/middlewares"
"github.com/thoas/go-funk"
)
func (s *service) basicAuthMiddleware(res *config.Resource) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Get data
basicConfig := s.cfg.AuthProviders.Basic[res.Provider]
basicAuthUserConfigList := res.Basic.Credentials
// Get logger from request
logEntry := log.GetLoggerFromContext(r.Context())
// Get bucket request context from request
brctx := middlewares.GetBucketRequestContext(r)
// Get response handler
resHan := responsehandler.GetResponseHandlerFromContext(r.Context())
// Get basic auth information
username, password, ok := r.BasicAuth()
if !ok {
// Create error
err := fmt.Errorf("no basic auth detected in request")
// Add header for basic auth realm
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, basicConfig.Realm))
// Check if bucket request context doesn't exist to use local default files
if brctx == nil {
responsehandler.GeneralUnauthorizedError(r, w, s.cfgManager, err)
} else {
resHan.UnauthorizedError(brctx.LoadFileContent, err)
}
return
}
// Create Basic auth user
buser := &models.BasicAuthUser{Username: username}
// Add user to request context by creating a new context
ctx := models.SetAuthenticatedUserInContext(r.Context(), buser)
// Create new request with new context
r = r.WithContext(ctx)
// Update response handler to have the latest context values
resHan.UpdateRequestAndResponse(r, w)
// Find user credentials
cred := funk.Find(basicAuthUserConfigList, func(cred *config.BasicAuthUserConfig) bool {
return cred.User == username
})
// Check if credential exists
if cred == nil {
// Create error
err := fmt.Errorf("username %s not found in authorized users", username)
// Add header for basic auth realm
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, basicConfig.Realm))
// Check if bucket request context doesn't exist to use local default files
if brctx == nil {
responsehandler.GeneralUnauthorizedError(r, w, s.cfgManager, err)
} else {
resHan.UnauthorizedError(brctx.LoadFileContent, err)
}
return
}
// Check password
if cred.(*config.BasicAuthUserConfig).Password.Value == "" || cred.(*config.BasicAuthUserConfig).Password.Value != password {
// Create error
err := fmt.Errorf("username %s not authorized", username)
// Add header for basic auth realm
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, basicConfig.Realm))
// Check if bucket request context doesn't exist to use local default files
if brctx == nil {
responsehandler.GeneralUnauthorizedError(r, w, s.cfgManager, err)
} else {
resHan.UnauthorizedError(brctx.LoadFileContent, err)
}
return
}
logEntry.Info("Basic auth user %s authenticated", buser.GetIdentifier())
s.metricsCl.IncAuthenticated("basic-auth", res.Provider)
next.ServeHTTP(w, r)
})
}
}