@@ -97,6 +97,8 @@ @interface FLTFirebaseAuthPlugin ()
9797@property (strong , nonatomic ) void (^appleCompletion)
9898 (PigeonUserCredential *_Nullable, FlutterError *_Nullable);
9999@property (strong , nonatomic ) AuthPigeonFirebaseApp *appleArguments;
100+ // / YES while an `ASAuthorizationController` Sign in with Apple flow is active.
101+ @property (nonatomic , assign ) BOOL appleSignInRequestInFlight;
100102
101103@end
102104
@@ -380,16 +382,25 @@ static void handleSignInWithApple(FLTFirebaseAuthPlugin *object, FIRAuthDataResu
380382 NSString *authorizationCode, NSError *error) {
381383 void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) =
382384 object.appleCompletion ;
383- if (completion == nil ) return ;
385+ if (completion == nil ) {
386+ object.appleSignInRequestInFlight = NO ;
387+ return ;
388+ }
384389
385390 if (error != nil ) {
386391 if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
392+ object.appleCompletion = nil ;
393+ object.appleSignInRequestInFlight = NO ;
387394 [object handleMultiFactorError: object.appleArguments completion: completion withError: error];
388395 } else {
396+ object.appleCompletion = nil ;
397+ object.appleSignInRequestInFlight = NO ;
389398 completion (nil , [FLTFirebaseAuthPlugin convertToFlutterError: error]);
390399 }
391400 return ;
392401 }
402+ object.appleCompletion = nil ;
403+ object.appleSignInRequestInFlight = NO ;
393404 completion ([PigeonParser getPigeonUserCredentialFromAuthResult: authResult
394405 authorizationCode: authorizationCode],
395406 nil );
@@ -406,6 +417,15 @@ - (void)authorizationController:(ASAuthorizationController *)controller
406417
407418 if (appleIDCredential.identityToken == nil ) {
408419 NSLog (@" Unable to fetch identity token." );
420+ void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) =
421+ self.appleCompletion ;
422+ self.appleCompletion = nil ;
423+ self.appleSignInRequestInFlight = NO ;
424+ if (completion != nil ) {
425+ completion (nil , [FlutterError errorWithCode: kErrCodeInvalidCredential
426+ message: kErrMsgInvalidCredential
427+ details: nil ]);
428+ }
409429 return ;
410430 }
411431
@@ -459,47 +479,62 @@ - (void)authorizationController:(ASAuthorizationController *)controller
459479 handleSignInWithApple (self, authResult, authorizationCode, error);
460480 }];
461481 }
482+ } else {
483+ void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) =
484+ self.appleCompletion ;
485+ self.appleCompletion = nil ;
486+ self.appleSignInRequestInFlight = NO ;
487+ if (completion != nil ) {
488+ completion (nil , [FlutterError errorWithCode: kErrCodeInvalidCredential
489+ message: kErrMsgInvalidCredential
490+ details: nil ]);
491+ }
462492 }
463493}
464494
465495- (void )authorizationController : (ASAuthorizationController *)controller
466496 didCompleteWithError : (NSError *)error API_AVAILABLE(macos(10.15 ), ios(13.0 )) {
497+ void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) =
498+ self.appleCompletion ;
499+ self.appleCompletion = nil ;
500+ self.appleSignInRequestInFlight = NO ;
501+
467502 NSLog (@" Sign in with Apple errored: %@ " , error);
503+ if (completion == nil ) {
504+ return ;
505+ }
506+
468507 switch (error.code ) {
469508 case ASAuthorizationErrorCanceled:
470- self.appleCompletion (
471- nil , [FlutterError errorWithCode: @" canceled"
472- message: @" The user canceled the authorization attempt."
473- details: nil ]);
509+ completion (nil , [FlutterError errorWithCode: @" canceled"
510+ message: @" The user canceled the authorization attempt."
511+ details: nil ]);
474512 break ;
475513
476514 case ASAuthorizationErrorInvalidResponse:
477- self.appleCompletion (
478- nil ,
479- [FlutterError errorWithCode: @" invalid-response"
480- message: @" The authorization request received an invalid response."
481- details: nil ]);
515+ completion (nil , [FlutterError
516+ errorWithCode: @" invalid-response"
517+ message: @" The authorization request received an invalid response."
518+ details: nil ]);
482519 break ;
483520
484521 case ASAuthorizationErrorNotHandled:
485- self.appleCompletion (nil ,
486- [FlutterError errorWithCode: @" not-handled"
487- message: @" The authorization request wasn’t handled."
488- details: nil ]);
522+ completion (nil , [FlutterError errorWithCode: @" not-handled"
523+ message: @" The authorization request wasn’t handled."
524+ details: nil ]);
489525 break ;
490526
491527 case ASAuthorizationErrorFailed:
492- self. appleCompletion (nil , [FlutterError errorWithCode: @" failed"
493- message: @" The authorization attempt failed."
494- details: nil ]);
528+ completion (nil , [FlutterError errorWithCode: @" failed"
529+ message: @" The authorization attempt failed."
530+ details: nil ]);
495531 break ;
496532
497533 case ASAuthorizationErrorUnknown:
498534 default :
499- self. appleCompletion (nil , [FLTFirebaseAuthPlugin convertToFlutterError: error]);
535+ completion (nil , [FLTFirebaseAuthPlugin convertToFlutterError: error]);
500536 break ;
501537 }
502- self.appleCompletion = nil ;
503538}
504539
505540- (void )handleInternalError : (nonnull void (^)(PigeonUserCredential *_Nullable,
@@ -570,10 +605,19 @@ static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, AuthPigeonFi
570605 void (^_Nonnull completion)(PigeonUserCredential *_Nullable,
571606 FlutterError *_Nullable)) {
572607 if (@available (iOS 13.0 , macOS 10.15 , *)) {
608+ if (object.appleSignInRequestInFlight ) {
609+ completion (nil ,
610+ [FlutterError errorWithCode: @" operation-not-allowed"
611+ message: @" A Sign in with Apple request is already in progress."
612+ details: nil ]);
613+ return ;
614+ }
615+
573616 NSString *nonce = [object randomNonce: 32 ];
574617 object.currentNonce = nonce;
575618 object.appleCompletion = completion;
576619 object.appleArguments = app;
620+ object.appleSignInRequestInFlight = YES ;
577621
578622 ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc ] init ];
579623
0 commit comments