Skip to content

Commit 7d09126

Browse files
committed
Add no-op permission APIs to authenticators
1 parent 6bc7971 commit 7d09126

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

auth/authenticator.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@ type Authenticator interface {
1919
// else returns an empty string.
2020
Validate(r *http.Request) (string, error)
2121
// ValidateAndReject is called on an HTTP API request and returns the username if request
22-
// is authenticated, else the request is rejected.
22+
// is authenticated, else returns an empty string and rejects the request.
2323
ValidateAndReject(w http.ResponseWriter, r *http.Request) string
24+
// HasPerm returns a boolean indicating whether or not the user has the requested permission.
25+
HasPerm(username string, permission string) (bool, error)
26+
// ValidatePermAndReject is called on an HTTP API request and returns the username if request is
27+
// authenticated, and a boolean indicating whether or not the user has the requested permission.
28+
// If unauthenticated or forbidden, the request is rejected with a 401 or 403 error respectively.
29+
ValidatePermAndReject(w http.ResponseWriter, r *http.Request, permission string) (string, bool)
2430
// CanManageAuth returns whether or not this authenticator can manage auth, i.e. users and tokens.
2531
CanManageAuth() bool
2632
// Login allows logging in a user and returning the token.
@@ -68,6 +74,22 @@ func (a *ReplaceableAuthenticator) ValidateAndReject(w http.ResponseWriter, r *h
6874
return a.Engine.ValidateAndReject(w, r)
6975
}
7076

77+
// HasPerm returns a boolean indicating whether or not the user has the requested permission.
78+
func (a *ReplaceableAuthenticator) HasPerm(username string, permission string) (bool, error) {
79+
a.EngineMutex.RLock()
80+
defer a.EngineMutex.RUnlock()
81+
return a.Engine.HasPerm(username, permission)
82+
}
83+
84+
// ValidatePermAndReject is called on an HTTP API request and returns the username if request is
85+
// authenticated, and a boolean indicating whether or not the user has the requested permission.
86+
// If unauthenticated or forbidden, the request is rejected with a 401 or 403 error respectively.
87+
func (a *ReplaceableAuthenticator) ValidatePermAndReject(w http.ResponseWriter, r *http.Request, permission string) (string, bool) {
88+
a.EngineMutex.RLock()
89+
defer a.EngineMutex.RUnlock()
90+
return a.Engine.ValidatePermAndReject(w, r, permission)
91+
}
92+
7193
// CanManageAuth returns whether or not this authenticator can manage auth, i.e. users and tokens.
7294
func (a *ReplaceableAuthenticator) CanManageAuth() bool {
7395
a.EngineMutex.RLock()

auth/memory.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (a *MemoryAuthenticator) Validate(r *http.Request) (string, error) {
8282
}
8383

8484
// ValidateAndReject is called on an HTTP API request and returns the username if request
85-
// is authenticated, else the request is rejected.
85+
// is authenticated, else returns an empty string and rejects the request.
8686
func (a *MemoryAuthenticator) ValidateAndReject(w http.ResponseWriter, r *http.Request) string {
8787
username, err := a.Validate(r)
8888
if err != nil {
@@ -99,6 +99,34 @@ func (a *MemoryAuthenticator) ValidateAndReject(w http.ResponseWriter, r *http.R
9999
return username
100100
}
101101

102+
// HasPerm returns a boolean indicating whether or not the user has the requested permission.
103+
func (a *MemoryAuthenticator) HasPerm(username string, permission string) (bool, error) {
104+
return true, nil
105+
}
106+
107+
// ValidatePermAndReject is called on an HTTP API request and returns the username if request is
108+
// authenticated, and a boolean indicating whether or not the user has the requested permission.
109+
// If unauthenticated or forbidden, the request is rejected with a 401 or 403 error respectively.
110+
func (a *MemoryAuthenticator) ValidatePermAndReject(w http.ResponseWriter, r *http.Request, permission string) (string, bool) {
111+
username := a.ValidateAndReject(w, r)
112+
if username == "" {
113+
return "", false
114+
}
115+
hasPerm, err := a.HasPerm(username, permission)
116+
if err != nil {
117+
w.Header().Set("content-type", "application/json")
118+
log.Println("An error occurred while validating authorization for an HTTP request!", err)
119+
http.Error(w, "{\"error\": \"Internal Server Error!\"}", http.StatusInternalServerError)
120+
return "", false
121+
} else if !hasPerm {
122+
w.Header().Set("content-type", "application/json")
123+
http.Error(w, "{\"error\": \"You are not allowed to access this resource!\"}",
124+
http.StatusForbidden)
125+
return "", false
126+
}
127+
return username, true
128+
}
129+
102130
// CanManageAuth returns whether or not this authenticator can manage auth, i.e. users and tokens.
103131
func (*MemoryAuthenticator) CanManageAuth() bool {
104132
return true

auth/redis.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func (a *RedisAuthenticator) getTokenData(conn redis.Conn, token string) (string
149149
}
150150

151151
// ValidateAndReject is called on an HTTP API request and returns the username if request
152-
// is authenticated, else the request is rejected.
152+
// is authenticated, else returns an empty string and rejects the request.
153153
func (a *RedisAuthenticator) ValidateAndReject(w http.ResponseWriter, r *http.Request) string {
154154
username, err := a.Validate(r)
155155
if err != nil {
@@ -166,6 +166,34 @@ func (a *RedisAuthenticator) ValidateAndReject(w http.ResponseWriter, r *http.Re
166166
return username
167167
}
168168

169+
// HasPerm returns a boolean indicating whether or not the user has the requested permission.
170+
func (a *RedisAuthenticator) HasPerm(username string, permission string) (bool, error) {
171+
return true, nil
172+
}
173+
174+
// ValidatePermAndReject is called on an HTTP API request and returns the username if request is
175+
// authenticated, and a boolean indicating whether or not the user has the requested permission.
176+
// If unauthenticated or forbidden, the request is rejected with a 401 or 403 error respectively.
177+
func (a *RedisAuthenticator) ValidatePermAndReject(w http.ResponseWriter, r *http.Request, permission string) (string, bool) {
178+
username := a.ValidateAndReject(w, r)
179+
if username == "" {
180+
return "", false
181+
}
182+
hasPerm, err := a.HasPerm(username, permission)
183+
if err != nil {
184+
w.Header().Set("content-type", "application/json")
185+
log.Println("An error occurred while validating authorization for an HTTP request!", err)
186+
http.Error(w, "{\"error\": \"Internal Server Error!\"}", http.StatusInternalServerError)
187+
return "", false
188+
} else if !hasPerm {
189+
w.Header().Set("content-type", "application/json")
190+
http.Error(w, "{\"error\": \"You are not allowed to access this resource!\"}",
191+
http.StatusForbidden)
192+
return "", false
193+
}
194+
return username, true
195+
}
196+
169197
// CanManageAuth returns whether or not this authenticator can manage auth, i.e. users and tokens.
170198
func (a *RedisAuthenticator) CanManageAuth() bool {
171199
return a.stopUserUpdates != nil

0 commit comments

Comments
 (0)