Skip to content

Commit c9589ed

Browse files
authored
Merge pull request #70 from appbaseio/fix/user-management
feat: update error messages + add response header for 401 errors
2 parents d74aa9c + ae73094 commit c9589ed

10 files changed

Lines changed: 29 additions & 2 deletions

File tree

middleware/ratelimiter/ratelimiter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func (rl *Ratelimiter) rateLimit(h http.HandlerFunc) http.HandlerFunc {
8686
// limit on Categories per second
8787
categoryLimit, err := reqPermission.GetLimitFor(*reqCategory)
8888
if err != nil {
89+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
8990
util.WriteBackError(w, err.Error(), http.StatusUnauthorized)
9091
return
9192
}

middleware/validate/acl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func validateACL(h http.HandlerFunc) http.HandlerFunc {
4848

4949
if !ok {
5050
msg := fmt.Sprintf(`credentials cannot access "%s" acl`, reqACL.String())
51+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
5152
util.WriteBackError(w, msg, http.StatusUnauthorized)
5253
return
5354
}

middleware/validate/category.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func validateCategory(h http.HandlerFunc) http.HandlerFunc {
4848

4949
if !ok {
5050
msg := fmt.Sprintf(`credential can't access "%s" category`, reqCategory.String())
51+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
5152
util.WriteBackError(w, msg, http.StatusUnauthorized)
5253
return
5354
}

middleware/validate/expiry.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func validateExpiry(h http.HandlerFunc) http.HandlerFunc {
4545

4646
if expired {
4747
msg := fmt.Sprintf("permission with username=%s is expired", reqPermission.Username)
48+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
4849
util.WriteBackError(w, msg, http.StatusUnauthorized)
4950
return
5051
}

middleware/validate/indices.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func indices(h http.HandlerFunc) http.HandlerFunc {
4848
return
4949
}
5050
if !ok {
51+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
5152
util.WriteBackError(w, "credentials cannot access cluster level routes", http.StatusUnauthorized)
5253
return
5354
}
@@ -61,6 +62,7 @@ func indices(h http.HandlerFunc) http.HandlerFunc {
6162
}
6263
if !ok {
6364
msg := fmt.Sprintf("credentials cannot access %v index/indices", reqIndices)
65+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
6466
util.WriteBackError(w, msg, http.StatusUnauthorized)
6567
return
6668
}

middleware/validate/op.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func operation(h http.HandlerFunc) http.HandlerFunc {
4848

4949
if !ok {
5050
msg := fmt.Sprintf(`credential cannot perform "%v" operation`, reqOp.String())
51+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
5152
util.WriteBackError(w, msg, http.StatusUnauthorized)
5253
return
5354
}

middleware/validate/referers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func referers(h http.HandlerFunc) http.HandlerFunc {
5959
}
6060

6161
if !validated {
62+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
6263
util.WriteBackError(w, "permission doesn't have required referers", http.StatusUnauthorized)
6364
return
6465
}

middleware/validate/sources.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func sources(h http.HandlerFunc) http.HandlerFunc {
3636
reqIP := iplookup.FromRequest(req)
3737
if reqIP == "" {
3838
msg := fmt.Sprintf(`failed to recognize request ip: "%s"`, reqIP)
39+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
3940
util.WriteBackError(w, msg, http.StatusUnauthorized)
4041
return
4142
}
@@ -70,6 +71,7 @@ func sources(h http.HandlerFunc) http.HandlerFunc {
7071
if !validated {
7172
msg := fmt.Sprintf(`permission with username %s doesn't have required sources. reqIP = %s, sources = %s`,
7273
reqPermission.Username, reqIP, allowedSources)
74+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
7375
util.WriteBackError(w, msg, http.StatusUnauthorized)
7476
return
7577
}

plugins/auth/middleware.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
106106
} else {
107107
msg = fmt.Sprintf("Unable to parse JWT: %v", err)
108108
}
109+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
109110
util.WriteBackError(w, msg, http.StatusUnauthorized)
110111
return
111112
}
@@ -118,10 +119,12 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
118119
} else if u, ok := claims["role"]; ok {
119120
role = u.(string)
120121
} else {
122+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
121123
util.WriteBackError(w, fmt.Sprintf("Invalid JWT"), http.StatusUnauthorized)
122124
return
123125
}
124126
} else {
127+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
125128
util.WriteBackError(w, fmt.Sprintf("Invalid JWT"), http.StatusUnauthorized)
126129
return
127130
}
@@ -133,6 +136,7 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
133136
if err != nil || obj == nil {
134137
msg := fmt.Sprintf("No API credentials match with provided role: %s", role)
135138
log.Errorln(logTag, ":", err)
139+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
136140
util.WriteBackError(w, msg, http.StatusUnauthorized)
137141
return
138142
}
@@ -141,12 +145,14 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
141145
if err != nil || obj == nil {
142146
msg := fmt.Sprintf("No API credentials match with provided username: %s", username)
143147
log.Errorln(logTag, ":", err)
148+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
144149
util.WriteBackError(w, msg, http.StatusUnauthorized)
145150
return
146151
}
147152
}
148153

149154
var authenticated bool
155+
var errorMsg = "invalid credentials provided"
150156

151157
// since we are able to fetch a result with the given credentials, we
152158
// do not need to validate the username and password.
@@ -156,6 +162,7 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
156162
// if the request is made to elasticsearch using user credentials, then the user has to be an admin
157163
reqUser := obj.(*user.User)
158164
if hasBasicAuth && bcrypt.CompareHashAndPassword([]byte(reqUser.Password), []byte(password)) != nil {
165+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
159166
util.WriteBackError(w, "invalid password", http.StatusUnauthorized)
160167
return
161168
}
@@ -165,6 +172,10 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
165172
authenticated = true
166173
}
167174

175+
if !authenticated {
176+
errorMsg = "only admin users are allowed to access elasticsearch"
177+
}
178+
168179
// cache the user
169180
if _, ok := a.cachedCredential(username); !ok {
170181
a.cacheCredential(username, reqUser)
@@ -179,12 +190,15 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
179190
{
180191
reqPermission := obj.(*permission.Permission)
181192
if hasBasicAuth && reqPermission.Password != password {
193+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
182194
util.WriteBackError(w, "invalid password", http.StatusUnauthorized)
183195
return
184196
}
185197

186198
if reqCategory.IsFromES() {
187199
authenticated = true
200+
} else {
201+
errorMsg = "credential is only allowed to access elasticsearch"
188202
}
189203

190204
// cache the permission
@@ -202,7 +216,8 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
202216
}
203217

204218
if !authenticated {
205-
util.WriteBackError(w, "invalid credentials provided", http.StatusUnauthorized)
219+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
220+
util.WriteBackError(w, errorMsg, http.StatusUnauthorized)
206221
return
207222
}
208223

plugins/users/middleware.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package users
22

33
import (
44
"fmt"
5-
log "github.com/sirupsen/logrus"
65
"net/http"
76

7+
log "github.com/sirupsen/logrus"
8+
89
"github.com/appbaseio/arc/middleware"
910
"github.com/appbaseio/arc/middleware/classify"
1011
"github.com/appbaseio/arc/middleware/validate"
@@ -68,6 +69,7 @@ func isAdmin(h http.HandlerFunc) http.HandlerFunc {
6869

6970
if !*reqUser.IsAdmin {
7071
msg := fmt.Sprintf(`user with "username"="%s" is not an admin`, reqUser.Username)
72+
w.Header().Set("www-authenticate", "Basic realm=\"Authentication Required\"")
7173
util.WriteBackError(w, msg, http.StatusUnauthorized)
7274
return
7375
}

0 commit comments

Comments
 (0)