@@ -112,6 +112,9 @@ public protocol SessionConfiguration: AnyObject, Sendable {
112112 /// while adding the password and tokens to the `keychainProtocol` instance. Additional
113113 /// Two-Factor Authentication implementations must be handled as well.
114114 ///
115+ /// - Note: 2FA detection now supports both `.badRequest` (400) and `.unauthorized` (401)
116+ /// responses containing the `AuthFactorTokenRequired` error.
117+ ///
115118 /// - Parameters:
116119 /// - handle: The hanle used for the account.
117120 /// - password: The password used for the account.
@@ -269,24 +272,41 @@ extension SessionConfiguration {
269272 )
270273 } catch let error as ATAPIError {
271274 switch error {
272- case . badRequest( error: let responseError) :
273- if responseError. error == " AuthFactorTokenRequired " {
274- twoFactorAuthenticationAttempts += 1
275- if twoFactorAuthenticationAttempts > maxTwoFactorAuthenticationAttempts {
276- throw ATAPIError . badRequest ( error: APIClientService . ATHTTPResponseError (
277- error: " TooManyTwoFactorAuthenticationAttempts " ,
278- message: " Too many invalid two-factor authentication codes. Please try again later. "
279- ) )
280- }
281-
282- // Ask the user for a new code, then continue the loop.
283- userCode = await waitForUserCode ( )
284- continue
285- } else {
286- throw error
275+ case . badRequest( error: let responseError) :
276+ if responseError. error == " AuthFactorTokenRequired " {
277+ twoFactorAuthenticationAttempts += 1
278+ if twoFactorAuthenticationAttempts > maxTwoFactorAuthenticationAttempts {
279+ throw ATAPIError . badRequest ( error: APIClientService . ATHTTPResponseError (
280+ error: " TooManyTwoFactorAuthenticationAttempts " ,
281+ message: " Too many invalid two-factor authentication codes. Please try again later. "
282+ ) )
283+ }
284+
285+ // Ask the user for a new code, then continue the loop.
286+ userCode = await waitForUserCode ( )
287+ continue
288+ } else {
289+ throw error
290+ }
291+ case . unauthorized( error: let responseError, wwwAuthenticate: _) :
292+ // Handle 2FA requirement that comes as unauthorized instead of badRequest
293+ if responseError. error == " AuthFactorTokenRequired " {
294+ twoFactorAuthenticationAttempts += 1
295+ if twoFactorAuthenticationAttempts > maxTwoFactorAuthenticationAttempts {
296+ throw ATAPIError . badRequest ( error: APIClientService . ATHTTPResponseError (
297+ error: " TooManyTwoFactorAuthenticationAttempts " ,
298+ message: " Too many invalid two-factor authentication codes. Please try again later. "
299+ ) )
287300 }
288- default :
301+
302+ // Ask the user for a new code, then continue the loop.
303+ userCode = await waitForUserCode ( )
304+ continue
305+ } else {
289306 throw error
307+ }
308+ default :
309+ throw error
290310 }
291311 } catch {
292312 throw error
0 commit comments