Skip to content
This repository was archived by the owner on Nov 25, 2024. It is now read-only.

Commit a616e37

Browse files
committed
refactoring user interactive auth:
- making members private as they aren't used outside of the package and in order to protect from concurrent writes - make the mutex protect the sessions only as they are written to concurrently
1 parent 46902e5 commit a616e37

File tree

1 file changed

+24
-26
lines changed

1 file changed

+24
-26
lines changed

clientapi/auth/user_interactive.go

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,13 @@ type userInteractiveFlow struct {
103103
// the user already has a valid access token, but we want to double-check
104104
// that it isn't stolen by re-authenticating them.
105105
type UserInteractive struct {
106-
sync.RWMutex
107-
Flows []userInteractiveFlow
106+
flows []userInteractiveFlow
108107
// Map of login type to implementation
109-
Types map[string]Type
108+
types map[string]Type
110109
// Map of session ID to completed login types, will need to be extended in future
111-
Sessions map[string][]string
110+
111+
mutex sync.RWMutex
112+
sessions map[string][]string
112113
}
113114

114115
func NewUserInteractive(userAccountAPI api.UserLoginAPI, cfg *config.ClientAPI) *UserInteractive {
@@ -117,22 +118,20 @@ func NewUserInteractive(userAccountAPI api.UserLoginAPI, cfg *config.ClientAPI)
117118
Config: cfg,
118119
}
119120
return &UserInteractive{
120-
Flows: []userInteractiveFlow{
121+
flows: []userInteractiveFlow{
121122
{
122123
Stages: []string{typePassword.Name()},
123124
},
124125
},
125-
Types: map[string]Type{
126+
types: map[string]Type{
126127
typePassword.Name(): typePassword,
127128
},
128-
Sessions: make(map[string][]string),
129+
sessions: make(map[string][]string),
129130
}
130131
}
131132

132133
func (u *UserInteractive) IsSingleStageFlow(authType string) bool {
133-
u.RLock()
134-
defer u.RUnlock()
135-
for _, f := range u.Flows {
134+
for _, f := range u.flows {
136135
if len(f.Stages) == 1 && f.Stages[0] == authType {
137136
return true
138137
}
@@ -141,10 +140,10 @@ func (u *UserInteractive) IsSingleStageFlow(authType string) bool {
141140
}
142141

143142
func (u *UserInteractive) AddCompletedStage(sessionID, authType string) {
144-
u.Lock()
143+
u.mutex.Lock()
145144
// TODO: Handle multi-stage flows
146-
delete(u.Sessions, sessionID)
147-
u.Unlock()
145+
delete(u.sessions, sessionID)
146+
u.mutex.Unlock()
148147
}
149148

150149
type Challenge struct {
@@ -157,10 +156,11 @@ type Challenge struct {
157156

158157
// Challenge returns an HTTP 401 with the supported flows for authenticating
159158
func (u *UserInteractive) challenge(sessionID string) *util.JSONResponse {
160-
u.RLock()
161-
completed := u.Sessions[sessionID]
162-
flows := u.Flows
163-
u.RUnlock()
159+
u.mutex.RLock()
160+
completed := u.sessions[sessionID]
161+
u.mutex.RUnlock()
162+
163+
flows := u.flows
164164

165165
return &util.JSONResponse{
166166
Code: 401,
@@ -183,9 +183,9 @@ func (u *UserInteractive) NewSession() *util.JSONResponse {
183183
JSON: spec.InternalServerError{},
184184
}
185185
}
186-
u.Lock()
187-
u.Sessions[sessionID] = []string{}
188-
u.Unlock()
186+
u.mutex.Lock()
187+
u.sessions[sessionID] = []string{}
188+
u.mutex.Unlock()
189189
return u.challenge(sessionID)
190190
}
191191

@@ -233,9 +233,7 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
233233
// extract the type so we know which login type to use
234234
authType := gjson.GetBytes(bodyBytes, "auth.type").Str
235235

236-
u.RLock()
237-
loginType, ok := u.Types[authType]
238-
u.RUnlock()
236+
loginType, ok := u.types[authType]
239237

240238
if !ok {
241239
return nil, &util.JSONResponse{
@@ -247,9 +245,9 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
247245
// retrieve the session
248246
sessionID := gjson.GetBytes(bodyBytes, "auth.session").Str
249247

250-
u.RLock()
251-
_, ok = u.Sessions[sessionID]
252-
u.RUnlock()
248+
u.mutex.RLock()
249+
_, ok = u.sessions[sessionID]
250+
u.mutex.RUnlock()
253251

254252
if !ok {
255253
// if the login type is part of a single stage flow then allow them to omit the session ID

0 commit comments

Comments
 (0)