Skip to content

Commit 6b9de70

Browse files
authored
fix: authentication issues caused by update/delete operations (#127)
* fix: auth cache * fix: remove todo note
1 parent 53da588 commit 6b9de70

4 files changed

Lines changed: 72 additions & 23 deletions

File tree

plugins/auth/auth.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,20 @@ var (
3636
once sync.Once
3737
)
3838

39-
// Auth (TODO - clear cache after fixed entries: LRU?)
39+
// Cache represents the struct for CredentialCache
40+
type Cache struct {
41+
mu sync.RWMutex
42+
cache map[string]credential.AuthCredential
43+
}
44+
45+
// CredentialCache represents the cached users/credentials where key is `username`
46+
var CredentialCache = Cache{
47+
mu: sync.RWMutex{},
48+
cache: make(map[string]credential.AuthCredential),
49+
}
50+
4051
type Auth struct {
4152
mu sync.Mutex
42-
credentialCache map[string]credential.AuthCredential
4353
jwtRsaPublicKey *rsa.PublicKey
4454
jwtRoleKey string
4555
es authService
@@ -50,9 +60,7 @@ type Auth struct {
5060
// the instance of the plugin, in order to avoid stateless duplicates.
5161
func Instance() *Auth {
5262
once.Do(func() {
53-
singleton = &Auth{
54-
credentialCache: make(map[string]credential.AuthCredential),
55-
}
63+
singleton = &Auth{}
5664
})
5765
return singleton
5866
}

plugins/auth/middleware.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
186186
}
187187

188188
// cache the user
189-
if _, ok := a.cachedCredential(username); !ok {
190-
a.cacheCredential(username, reqUser)
189+
if _, ok := GetCachedCredential(username); !ok {
190+
SaveCredentialToCache(username, reqUser)
191191
}
192192

193193
// store request user and credential identifier in the context
@@ -212,8 +212,8 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
212212
}
213213

214214
// cache the permission
215-
if _, ok := a.cachedCredential(username); !ok {
216-
a.cacheCredential(username, reqPermission)
215+
if _, ok := GetCachedCredential(username); !ok {
216+
SaveCredentialToCache(username, reqPermission)
217217
}
218218

219219
// store the request permission and credential identifier in the context
@@ -234,42 +234,45 @@ func (a *Auth) basicAuth(h http.HandlerFunc) http.HandlerFunc {
234234
// remove user/permission from cache on write operation
235235
if *reqOp == op.Write || *reqOp == op.Delete {
236236
username := mux.Vars(req)["username"]
237-
a.removeCredentialFromCache(username)
237+
RemoveCredentialFromCache(username)
238238
}
239239

240240
h(w, req)
241241
}
242242
}
243243

244244
func (a *Auth) getCredential(ctx context.Context, username string) (credential.AuthCredential, error) {
245-
c, ok := a.cachedCredential(username)
245+
c, ok := GetCachedCredential(username)
246246
if ok {
247247
return c, nil
248248
}
249249
return a.es.getCredential(ctx, username)
250250
}
251251

252-
func (a *Auth) cachedCredential(username string) (credential.AuthCredential, bool) {
253-
a.mu.Lock()
254-
defer a.mu.Unlock()
255-
if c, ok := a.credentialCache[username]; ok {
252+
// GetCachedCredential returns the cached credential
253+
func GetCachedCredential(username string) (credential.AuthCredential, bool) {
254+
CredentialCache.mu.Lock()
255+
defer CredentialCache.mu.Unlock()
256+
if c, ok := CredentialCache.cache[username]; ok {
256257
return c, ok
257258
}
258259
return nil, false
259260
}
260261

261-
func (a *Auth) removeCredentialFromCache(username string) {
262-
a.mu.Lock()
263-
defer a.mu.Unlock()
264-
delete(a.credentialCache, username)
262+
// RemoveCredentialFromCache removes the credential from the cache
263+
func RemoveCredentialFromCache(username string) {
264+
CredentialCache.mu.Lock()
265+
defer CredentialCache.mu.Unlock()
266+
delete(CredentialCache.cache, username)
265267
}
266268

267-
func (a *Auth) cacheCredential(username string, c credential.AuthCredential) {
269+
// SaveCredentialToCache saves the credential to the cache
270+
func SaveCredentialToCache(username string, c credential.AuthCredential) {
268271
if c == nil {
269272
log.Println(logTag, ": cannot cache 'nil' credential, skipping...")
270273
return
271274
}
272-
a.mu.Lock()
273-
defer a.mu.Unlock()
274-
a.credentialCache[username] = c
275+
CredentialCache.mu.Lock()
276+
CredentialCache.cache[username] = c
277+
CredentialCache.mu.Unlock()
275278
}

plugins/permissions/handlers.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/appbaseio/arc/model/index"
1313
"github.com/appbaseio/arc/model/permission"
1414
"github.com/appbaseio/arc/model/user"
15+
"github.com/appbaseio/arc/plugins/auth"
1516
"github.com/appbaseio/arc/util"
1617
"github.com/gorilla/mux"
1718
)
@@ -255,6 +256,10 @@ func (p *permissions) deletePermission() http.HandlerFunc {
255256

256257
ok, err := p.es.deletePermission(req.Context(), username)
257258
if ok && err == nil {
259+
// Clear username record from the cache
260+
auth.ClearPassword(username)
261+
// Clear user record from the user cache
262+
auth.RemoveCredentialFromCache(username)
258263
msg := fmt.Sprintf(`permission with "username"="%s" deleted`, username)
259264
util.WriteBackMessage(w, msg, http.StatusOK)
260265
return

plugins/users/handlers.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ func (u *Users) postUser() http.HandlerFunc {
118118
msg := fmt.Sprintf("an error occurred while hashing password: %v", userBody.Password)
119119
log.Errorln(logTag, ":", msg, ":", err)
120120
util.WriteBackError(w, msg, http.StatusInternalServerError)
121+
return
121122
}
122123

123124
var newUser *user.User
@@ -211,10 +212,24 @@ func (u *Users) patchUser() http.HandlerFunc {
211212
}
212213
}
213214

215+
// If user is trying to update the password then store the hashed password
216+
if patch["password"] != nil {
217+
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(userBody.Password), bcrypt.DefaultCost)
218+
if err != nil {
219+
msg := fmt.Sprintf("an error occurred while hashing password: %v", userBody.Password)
220+
log.Errorln(logTag, ":", msg, ":", err)
221+
util.WriteBackError(w, msg, http.StatusInternalServerError)
222+
return
223+
}
224+
patch["password"] = string(hashedPassword)
225+
}
226+
214227
_, err2 := u.es.patchUser(req.Context(), username, patch)
215228
if err2 == nil {
216229
// Clear username record from the cache
217230
auth.ClearPassword(username)
231+
// Clear user record from the user cache
232+
auth.RemoveCredentialFromCache(username)
218233
util.WriteBackMessage(w, "User is updated successfully", http.StatusOK)
219234
return
220235
}
@@ -284,10 +299,24 @@ func (u *Users) patchUserWithUsername() http.HandlerFunc {
284299
}
285300
}
286301

302+
// If user is trying to update the password then store the hashed password
303+
if patch["password"] != nil {
304+
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(userBody.Password), bcrypt.DefaultCost)
305+
if err != nil {
306+
msg := fmt.Sprintf("an error occurred while hashing password: %v", userBody.Password)
307+
log.Errorln(logTag, ":", msg, ":", err)
308+
util.WriteBackError(w, msg, http.StatusInternalServerError)
309+
return
310+
}
311+
patch["password"] = string(hashedPassword)
312+
}
313+
287314
_, err2 := u.es.patchUser(req.Context(), username, patch)
288315
if err2 == nil {
289316
// Clear username record from the cache
290317
auth.ClearPassword(username)
318+
// Clear user record from the user cache
319+
auth.RemoveCredentialFromCache(username)
291320
util.WriteBackMessage(w, "User is updated successfully", http.StatusOK)
292321
return
293322
}
@@ -306,6 +335,8 @@ func (u *Users) deleteUser() http.HandlerFunc {
306335
if ok && err == nil {
307336
// Clear username record from the cache
308337
auth.ClearPassword(username)
338+
// Clear user record from the user cache
339+
auth.RemoveCredentialFromCache(username)
309340
msg := fmt.Sprintf(`user with "username"="%s" deleted`, username)
310341
util.WriteBackMessage(w, msg, http.StatusOK)
311342
return
@@ -330,6 +361,8 @@ func (u *Users) deleteUserWithUsername() http.HandlerFunc {
330361
if ok && err == nil {
331362
// Clear username record from the cache
332363
auth.ClearPassword(username)
364+
// Clear user record from the user cache
365+
auth.RemoveCredentialFromCache(username)
333366
msg := fmt.Sprintf(`user with "username"="%s" deleted`, username)
334367
util.WriteBackMessage(w, msg, http.StatusOK)
335368
return

0 commit comments

Comments
 (0)