@@ -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.
105105type 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
114115func 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
132133func (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
143142func (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
150149type Challenge struct {
@@ -157,10 +156,11 @@ type Challenge struct {
157156
158157// Challenge returns an HTTP 401 with the supported flows for authenticating
159158func (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