Skip to content

Commit 5a03a85

Browse files
authored
feat(auth): add all providers available to MFA (#9159)
* feat(auth): add all providers available to MFA * feat(auth, iOS): add all providers available to MFA * feat(auth, web): add all providers available to MFA
1 parent d1f9631 commit 5a03a85

File tree

3 files changed

+131
-87
lines changed

3 files changed

+131
-87
lines changed

packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,11 @@ private Task<Map<String, Object>> signInWithCredential(Map<String, Object> argum
771771
AuthResult authResult = Tasks.await(firebaseAuth.signInWithCredential(credential));
772772
taskCompletionSource.setResult(parseAuthResult(authResult));
773773
} catch (Exception e) {
774-
taskCompletionSource.setException(e);
774+
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
775+
handleMultiFactorException(arguments, taskCompletionSource, e);
776+
} else {
777+
taskCompletionSource.setException(e);
778+
}
775779
}
776780
});
777781

@@ -791,7 +795,11 @@ private Task<Map<String, Object>> signInWithCustomToken(Map<String, Object> argu
791795

792796
taskCompletionSource.setResult(parseAuthResult(authResult));
793797
} catch (Exception e) {
794-
taskCompletionSource.setException(e);
798+
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
799+
handleMultiFactorException(arguments, taskCompletionSource, e);
800+
} else {
801+
taskCompletionSource.setException(e);
802+
}
795803
}
796804
});
797805

@@ -814,41 +822,48 @@ private Task<Map<String, Object>> signInWithEmailAndPassword(Map<String, Object>
814822
taskCompletionSource.setResult(parseAuthResult(authResult));
815823
} catch (Exception e) {
816824
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
817-
final FirebaseAuthMultiFactorException multiFactorException =
818-
(FirebaseAuthMultiFactorException) e.getCause();
819-
Map<String, Object> output = new HashMap<>();
825+
handleMultiFactorException(arguments, taskCompletionSource, e);
826+
} else {
827+
taskCompletionSource.setException(e);
828+
}
829+
}
830+
});
820831

821-
MultiFactorResolver multiFactorResolver = multiFactorException.getResolver();
822-
final List<MultiFactorInfo> hints = multiFactorResolver.getHints();
832+
return taskCompletionSource.getTask();
833+
}
823834

824-
final MultiFactorSession session = multiFactorResolver.getSession();
825-
final String sessionId = UUID.randomUUID().toString();
826-
multiFactorSessionMap.put(sessionId, session);
835+
private void handleMultiFactorException(
836+
Map<String, Object> arguments,
837+
TaskCompletionSource<Map<String, Object>> taskCompletionSource,
838+
Exception e) {
839+
final FirebaseAuthMultiFactorException multiFactorException =
840+
(FirebaseAuthMultiFactorException) e.getCause();
841+
Map<String, Object> output = new HashMap<>();
827842

828-
final String resolverId = UUID.randomUUID().toString();
829-
multiFactorResolverMap.put(resolverId, multiFactorResolver);
843+
MultiFactorResolver multiFactorResolver = multiFactorException.getResolver();
844+
final List<MultiFactorInfo> hints = multiFactorResolver.getHints();
830845

831-
final List<Map<String, Object>> pigeonHints = multiFactorInfoToMap(hints);
846+
final MultiFactorSession session = multiFactorResolver.getSession();
847+
final String sessionId = UUID.randomUUID().toString();
848+
multiFactorSessionMap.put(sessionId, session);
832849

833-
output.put(Constants.APP_NAME, getAuth(arguments).getApp().getName());
850+
final String resolverId = UUID.randomUUID().toString();
851+
multiFactorResolverMap.put(resolverId, multiFactorResolver);
834852

835-
output.put(Constants.MULTI_FACTOR_HINTS, pigeonHints);
853+
final List<Map<String, Object>> pigeonHints = multiFactorInfoToMap(hints);
836854

837-
output.put(Constants.MULTI_FACTOR_SESSION_ID, sessionId);
838-
output.put(Constants.MULTI_FACTOR_RESOLVER_ID, resolverId);
855+
output.put(Constants.APP_NAME, getAuth(arguments).getApp().getName());
839856

840-
taskCompletionSource.setException(
841-
new FlutterFirebaseAuthPluginException(
842-
multiFactorException.getErrorCode(),
843-
multiFactorException.getLocalizedMessage(),
844-
output));
845-
} else {
846-
taskCompletionSource.setException(e);
847-
}
848-
}
849-
});
857+
output.put(Constants.MULTI_FACTOR_HINTS, pigeonHints);
850858

851-
return taskCompletionSource.getTask();
859+
output.put(Constants.MULTI_FACTOR_SESSION_ID, sessionId);
860+
output.put(Constants.MULTI_FACTOR_RESOLVER_ID, resolverId);
861+
862+
taskCompletionSource.setException(
863+
new FlutterFirebaseAuthPluginException(
864+
multiFactorException.getErrorCode(),
865+
multiFactorException.getLocalizedMessage(),
866+
output));
852867
}
853868

854869
private List<GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo> multiFactorInfoToPigeon(
@@ -899,7 +914,11 @@ private Task<Map<String, Object>> signInWithEmailLink(Map<String, Object> argume
899914
AuthResult authResult = Tasks.await(firebaseAuth.signInWithEmailLink(email, emailLink));
900915
taskCompletionSource.setResult(parseAuthResult(authResult));
901916
} catch (Exception e) {
902-
taskCompletionSource.setException(e);
917+
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
918+
handleMultiFactorException(arguments, taskCompletionSource, e);
919+
} else {
920+
taskCompletionSource.setException(e);
921+
}
903922
}
904923
});
905924

@@ -1547,7 +1566,11 @@ private Task<Map<String, Object>> signInWithAuthProvider(Map<String, Object> arg
15471566
/* activity= */ activity, provider.build()));
15481567
taskCompletionSource.setResult(parseAuthResult(authResult));
15491568
} catch (Exception e) {
1550-
taskCompletionSource.setException(e);
1569+
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
1570+
handleMultiFactorException(arguments, taskCompletionSource, e);
1571+
} else {
1572+
taskCompletionSource.setException(e);
1573+
}
15511574
}
15521575
});
15531576

packages/firebase_auth/firebase_auth/ios/Classes/FLTFirebaseAuthPlugin.m

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,11 @@ - (void)signInWithCredential:(id)arguments
475475
// error.
476476
result.error(nil, firebaseDictionary[@"message"], nil, nil);
477477
} else {
478-
result.error(nil, nil, nil, error);
478+
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
479+
[self handleMultiFactorError:arguments withResult:result withError:error];
480+
} else {
481+
result.error(nil, nil, nil, error);
482+
}
479483
}
480484
} else {
481485
result.success(authResult);
@@ -498,8 +502,13 @@ - (void)signInWithAuthProvider:(id)arguments
498502
completion:^(FIRAuthCredential *_Nullable credential,
499503
NSError *_Nullable error) {
500504
if (error) {
501-
result.error(kErrCodeInvalidCredential, kErrMsgInvalidCredential, nil,
502-
nil);
505+
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
506+
[self handleMultiFactorError:arguments
507+
withResult:result
508+
withError:error];
509+
} else {
510+
result.error(nil, nil, nil, error);
511+
}
503512
return;
504513
}
505514
if (credential) {
@@ -582,13 +591,66 @@ - (void)signInWithCustomToken:(id)arguments
582591
[auth signInWithCustomToken:arguments[kArgumentToken]
583592
completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
584593
if (error != nil) {
585-
result.error(nil, nil, nil, error);
594+
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
595+
[self handleMultiFactorError:arguments withResult:result withError:error];
596+
} else {
597+
result.error(nil, nil, nil, error);
598+
}
586599
} else {
587600
result.success(authResult);
588601
}
589602
}];
590603
}
591604

605+
- (void)handleMultiFactorError:(id)arguments
606+
withResult:(FLTFirebaseMethodCallResult *)result
607+
withError:(NSError *_Nullable)error {
608+
#if TARGET_OS_OSX
609+
result.error(nil, nil, nil, error);
610+
#else
611+
612+
FIRMultiFactorResolver *resolver =
613+
(FIRMultiFactorResolver *)error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
614+
615+
NSArray<FIRMultiFactorInfo *> *hints = resolver.hints;
616+
FIRMultiFactorSession *session = resolver.session;
617+
618+
NSString *sessionId = [[NSUUID UUID] UUIDString];
619+
self->_multiFactorSessionMap[sessionId] = session;
620+
621+
NSString *resolverId = [[NSUUID UUID] UUIDString];
622+
self->_multiFactorResolverMap[resolverId] = resolver;
623+
624+
NSMutableArray<NSDictionary *> *pigeonHints = [NSMutableArray array];
625+
626+
for (FIRMultiFactorInfo *multiFactorInfo in hints) {
627+
NSString *phoneNumber;
628+
if ([multiFactorInfo class] == [FIRPhoneMultiFactorInfo class]) {
629+
FIRPhoneMultiFactorInfo *phoneFactorInfo = (FIRPhoneMultiFactorInfo *)multiFactorInfo;
630+
phoneNumber = phoneFactorInfo.phoneNumber;
631+
}
632+
633+
PigeonMultiFactorInfo *object = [PigeonMultiFactorInfo
634+
makeWithDisplayName:multiFactorInfo.displayName
635+
enrollmentTimestamp:[NSNumber numberWithDouble:multiFactorInfo.enrollmentDate
636+
.timeIntervalSince1970]
637+
factorId:multiFactorInfo.factorID
638+
uid:multiFactorInfo.UID
639+
phoneNumber:phoneNumber];
640+
641+
[pigeonHints addObject:object.toMap];
642+
}
643+
644+
NSDictionary *output = @{
645+
kAppName : arguments[kAppName],
646+
kArgumentMultiFactorHints : pigeonHints,
647+
kArgumentMultiFactorSessionId : sessionId,
648+
kArgumentMultiFactorResolverId : resolverId,
649+
};
650+
result.error(nil, nil, output, error);
651+
#endif
652+
}
653+
592654
- (void)signInWithEmailAndPassword:(id)arguments
593655
withMethodCallResult:(FLTFirebaseMethodCallResult *)result {
594656
FIRAuth *auth = [self getFIRAuthFromArguments:arguments];
@@ -597,52 +659,7 @@ - (void)signInWithEmailAndPassword:(id)arguments
597659
completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
598660
if (error != nil) {
599661
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
600-
#if TARGET_OS_OSX
601-
result.error(nil, nil, nil, error);
602-
#else
603-
FIRMultiFactorResolver *resolver =
604-
(FIRMultiFactorResolver *)
605-
error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
606-
607-
NSArray<FIRMultiFactorInfo *> *hints = resolver.hints;
608-
FIRMultiFactorSession *session = resolver.session;
609-
610-
NSString *sessionId = [[NSUUID UUID] UUIDString];
611-
self->_multiFactorSessionMap[sessionId] = session;
612-
613-
NSString *resolverId = [[NSUUID UUID] UUIDString];
614-
self->_multiFactorResolverMap[resolverId] = resolver;
615-
616-
NSMutableArray<NSDictionary *> *pigeonHints = [NSMutableArray array];
617-
618-
for (FIRMultiFactorInfo *multiFactorInfo in hints) {
619-
NSString *phoneNumber;
620-
if ([multiFactorInfo class] == [FIRPhoneMultiFactorInfo class]) {
621-
FIRPhoneMultiFactorInfo *phoneFactorInfo =
622-
(FIRPhoneMultiFactorInfo *)multiFactorInfo;
623-
phoneNumber = phoneFactorInfo.phoneNumber;
624-
}
625-
626-
PigeonMultiFactorInfo *object = [PigeonMultiFactorInfo
627-
makeWithDisplayName:multiFactorInfo.displayName
628-
enrollmentTimestamp:[NSNumber numberWithDouble:multiFactorInfo.enrollmentDate
629-
.timeIntervalSince1970]
630-
factorId:multiFactorInfo.factorID
631-
uid:multiFactorInfo.UID
632-
phoneNumber:phoneNumber];
633-
634-
[pigeonHints addObject:object.toMap];
635-
}
636-
637-
NSDictionary *output = @{
638-
kAppName : arguments[kAppName],
639-
kArgumentMultiFactorHints : pigeonHints,
640-
kArgumentMultiFactorSessionId : sessionId,
641-
kArgumentMultiFactorResolverId : resolverId,
642-
};
643-
result.error(nil, nil, output, error);
644-
#endif
645-
662+
[self handleMultiFactorError:arguments withResult:result withError:error];
646663
} else {
647664
result.error(nil, nil, nil, error);
648665
}
@@ -659,7 +676,11 @@ - (void)signInWithEmailLink:(id)arguments
659676
link:arguments[@"emailLink"]
660677
completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
661678
if (error != nil) {
662-
result.error(nil, nil, nil, error);
679+
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
680+
[self handleMultiFactorError:arguments withResult:result withError:error];
681+
} else {
682+
result.error(nil, nil, nil, error);
683+
}
663684
} else {
664685
result.success(authResult);
665686
}

packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
303303
await delegate
304304
.signInWithCredential(convertPlatformCredential(credential)!));
305305
} catch (e) {
306-
throw getFirebaseAuthException(e);
306+
throw getFirebaseAuthException(e, _webAuth);
307307
}
308308
}
309309

@@ -313,7 +313,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
313313
return UserCredentialWeb(
314314
this, await delegate.signInWithCustomToken(token));
315315
} catch (e) {
316-
throw getFirebaseAuthException(e);
316+
throw getFirebaseAuthException(e, _webAuth);
317317
}
318318
}
319319

@@ -335,7 +335,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
335335
return UserCredentialWeb(
336336
this, await delegate.signInWithEmailLink(email, emailLink));
337337
} catch (e) {
338-
throw getFirebaseAuthException(e);
338+
throw getFirebaseAuthException(e, _webAuth);
339339
}
340340
}
341341

@@ -351,7 +351,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
351351
return ConfirmationResultWeb(
352352
this, await delegate.signInWithPhoneNumber(phoneNumber, verifier));
353353
} catch (e) {
354-
throw getFirebaseAuthException(e);
354+
throw getFirebaseAuthException(e, _webAuth);
355355
}
356356
}
357357

@@ -363,7 +363,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
363363
await delegate.signInWithPopup(convertPlatformAuthProvider(provider)),
364364
);
365365
} catch (e) {
366-
throw getFirebaseAuthException(e);
366+
throw getFirebaseAuthException(e, _webAuth);
367367
}
368368
}
369369

@@ -372,7 +372,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
372372
try {
373373
return delegate.signInWithRedirect(convertPlatformAuthProvider(provider));
374374
} catch (e) {
375-
throw getFirebaseAuthException(e);
375+
throw getFirebaseAuthException(e, _webAuth);
376376
}
377377
}
378378

0 commit comments

Comments
 (0)