@@ -16,7 +16,7 @@ import CommonCrypto
1616class AuthenticationProvider {
1717 private weak var client : Client !
1818 private( set) var isAuthenticating = false
19-
19+
2020 required init ( client: Client ) {
2121 self . client = client
2222 }
@@ -132,7 +132,7 @@ class AuthenticationProvider {
132132 throw Error . missingClientAuthentication. set ( request: request)
133133 }
134134
135- return sendOAuthRequest ( grantType: grantType, parameters: parameters)
135+ return try sendOAuthRequest ( grantType: grantType, parameters: parameters)
136136 . flatMap { [ weak self] _ -> Single < Request > in
137137 guard let self = self else {
138138 return Single< Request> . never( )
@@ -141,7 +141,15 @@ class AuthenticationProvider {
141141 }
142142 }
143143
144- func sendOAuthRequest( grantType: OAuthenticationGrantType , parameters: Parameters ? = nil ) -> Single < Void > {
144+ func sendOAuthRequest( grantType: OAuthenticationGrantType , parameters: Parameters ? = nil ) throws -> Single < Void > {
145+
146+ if isAuthenticating {
147+ client. logger? . trace ( " Already authenticating, stopping the concurrent request " )
148+ throw Error . concurrentAuthentication
149+ }
150+
151+ isAuthenticating = true
152+
145153 var parameters = parameters ?? [ : ]
146154 parameters [ " grant_type " ] = grantType. rawValue
147155
@@ -161,16 +169,14 @@ class AuthenticationProvider {
161169 " access_token " : client. config. logging. maskTokens ? . halfMasked : . default,
162170 " refresh_token " : client. config. logging. maskTokens ? . halfMasked : . default,
163171 ] )
164-
165172 }
166173
167- isAuthenticating = true
168-
169174 return client. request ( request) . flatMap { [ weak self, client] json in
170175 let accessToken = try json. map ( to: AccessToken . self)
171176 accessToken. host = client? . authenticationHost ?? " "
172177 accessToken. grantType = grantType
173178 accessToken. store ( )
179+
174180 client? . logger? . debug ( " Store access-token: \( optionalDescription ( accessToken) ) " )
175181 client? . authorizationGrantTypeSubject. onNext ( accessToken. grantType)
176182 self ? . isAuthenticating = false
@@ -189,6 +195,7 @@ class AuthenticationProvider {
189195 // So we can completely remove the access-token, since it is in no way able to revalidate.
190196 client? . logger? . warning ( " Clearing access-token; invalid refresh-token " )
191197 client? . clearAccessToken ( )
198+
192199 throw Error . refreshTokenInvalidated
193200 }
194201 }
@@ -225,9 +232,7 @@ class AuthenticationProvider {
225232
226233 authURLString += " &code_challenge= \( codeChallenge) &code_challenge_method=S256 "
227234 }
228-
229- print ( " authUrl: \( authURLString) " )
230-
235+
231236 guard let authURL = URL ( string: authURLString) else {
232237 observer ( . failure( Error . invalidUrl) )
233238 return Disposables . create ( )
@@ -255,7 +260,11 @@ class AuthenticationProvider {
255260 parameters [ " code_verifier " ] = codeVerifier
256261 }
257262
258- return sendOAuthRequest ( grantType: . authorizationCode, parameters: parameters)
263+ do {
264+ return try sendOAuthRequest ( grantType: . authorizationCode, parameters: parameters)
265+ } catch {
266+ return Single< Void> . error( error)
267+ }
259268 }
260269
261270 private func _createCodeVerifier( ) -> String {
@@ -326,7 +335,12 @@ class AuthenticationProvider {
326335
327336 accessToken. invalidate ( )
328337 return client. request ( request)
338+
339+ } else if error == Error . concurrentAuthentication {
340+ // Retry the request, which will probably add it to the queue because there's an authentication request pending
341+ return client. request ( request)
329342 }
343+
330344 throw error
331345 }
332346}
0 commit comments