Skip to content

fix(auth): properly propagate the FirebaseAuthMultiFactorException for all reauthenticate and link methods #9700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 24, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1128,6 +1128,10 @@ private Task<Map<String, Object>> linkUserWithCredential(Map<String, Object> arg

taskCompletionSource.setResult(parseAuthResult(authResult));
} catch (Exception e) {
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
handleMultiFactorException(arguments, taskCompletionSource, e);
return;
}
String message = e.getMessage();

if (message != null
@@ -1169,7 +1173,11 @@ private Task<Map<String, Object>> reauthenticateUserWithCredential(
Tasks.await(firebaseUser.reauthenticateAndRetrieveData(credential));
taskCompletionSource.setResult(parseAuthResult(authResult));
} catch (Exception e) {
taskCompletionSource.setException(e);
if (e.getCause() instanceof FirebaseAuthMultiFactorException) {
handleMultiFactorException(arguments, taskCompletionSource, e);
} else {
taskCompletionSource.setException(e);
}
}
});

Original file line number Diff line number Diff line change
@@ -1064,7 +1064,13 @@ - (void)userLinkWithCredential:(id)arguments
[currentUser linkWithCredential:credential
completion:^(FIRAuthDataResult *authResult, NSError *error) {
if (error != nil) {
result.error(nil, nil, nil, error);
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
[self handleMultiFactorError:arguments
withResult:result
withError:error];
} else {
result.error(nil, nil, nil, error);
}
} else {
result.success(authResult);
}
@@ -1090,7 +1096,13 @@ - (void)userReauthenticateUserWithCredential:(id)arguments
[currentUser reauthenticateWithCredential:credential
completion:^(FIRAuthDataResult *authResult, NSError *error) {
if (error != nil) {
result.error(nil, nil, nil, error);
if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
[self handleMultiFactorError:arguments
withResult:result
withError:error];
} else {
result.error(nil, nil, nil, error);
}
} else {
result.success(authResult);
}
58 changes: 41 additions & 17 deletions packages/firebase_auth/firebase_auth/lib/src/user.dart
Original file line number Diff line number Diff line change
@@ -184,10 +184,16 @@ class User {
/// - Thrown if the credential is a [PhoneAuthProvider.credential] and the
/// verification ID of the credential is not valid.
Future<UserCredential> linkWithCredential(AuthCredential credential) async {
return UserCredential._(
_auth,
await _delegate.linkWithCredential(credential),
);
try {
return UserCredential._(
_auth,
await _delegate.linkWithCredential(credential),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(_auth, e);
} catch (e) {
rethrow;
}
}

/// Links with an AuthProvider using native authentication flow.
@@ -273,10 +279,16 @@ class User {
Future<UserCredential> reauthenticateWithProvider(
AuthProvider provider,
) async {
return UserCredential._(
_auth,
await _delegate.reauthenticateWithProvider(provider),
);
try {
return UserCredential._(
_auth,
await _delegate.reauthenticateWithProvider(provider),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(_auth, e);
} catch (e) {
rethrow;
}
}

/// Links the user account with the given provider.
@@ -407,12 +419,18 @@ class User {
// also clear that instance before proceeding.
bool mustClear = verifier == null;
verifier ??= RecaptchaVerifier(auth: _delegate.auth);
final result =
await _delegate.linkWithPhoneNumber(phoneNumber, verifier.delegate);
if (mustClear) {
verifier.clear();
try {
final result =
await _delegate.linkWithPhoneNumber(phoneNumber, verifier.delegate);
if (mustClear) {
verifier.clear();
}
return ConfirmationResult._(_auth, result);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(_auth, e);
} catch (e) {
rethrow;
}
return ConfirmationResult._(_auth, result);
}

/// Re-authenticates a user using a fresh credential.
@@ -447,10 +465,16 @@ class User {
Future<UserCredential> reauthenticateWithCredential(
AuthCredential credential,
) async {
return UserCredential._(
_auth,
await _delegate.reauthenticateWithCredential(credential),
);
try {
return UserCredential._(
_auth,
await _delegate.reauthenticateWithCredential(credential),
);
} on FirebaseAuthMultiFactorExceptionPlatform catch (e) {
throw FirebaseAuthMultiFactorException._(_auth, e);
} catch (e) {
rethrow;
}
}

/// Refreshes the current user, if signed in.
71 changes: 53 additions & 18 deletions packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart
Original file line number Diff line number Diff line change
@@ -57,8 +57,12 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
if (webUser == null) {
return null;
} else {
return UserWeb(this,
MultiFactorWeb(this, multi_factor.multiFactor(webUser)), webUser);
return UserWeb(
this,
MultiFactorWeb(this, multi_factor.multiFactor(webUser)),
webUser,
_webAuth,
);
}
}).listen((UserWeb? webUser) {
_authStateChangesListeners[app.name]!.add(webUser);
@@ -70,8 +74,12 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
if (webUser == null) {
return null;
} else {
return UserWeb(this,
MultiFactorWeb(this, multi_factor.multiFactor(webUser)), webUser);
return UserWeb(
this,
MultiFactorWeb(this, multi_factor.multiFactor(webUser)),
webUser,
_webAuth,
);
}
}).listen((UserWeb? webUser) {
_idTokenChangesListeners[app.name]!.add(webUser);
@@ -136,9 +144,11 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
}

return UserWeb(
this,
MultiFactorWeb(this, multi_factor.multiFactor(delegate.currentUser!)),
delegate.currentUser!);
this,
MultiFactorWeb(this, multi_factor.multiFactor(delegate.currentUser!)),
delegate.currentUser!,
_webAuth,
);
}

@override
@@ -192,6 +202,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
return UserCredentialWeb(
this,
await delegate.createUserWithEmailAndPassword(email, password),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e);
@@ -210,7 +221,11 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
@override
Future<UserCredentialPlatform> getRedirectResult() async {
try {
return UserCredentialWeb(this, await delegate.getRedirectResult());
return UserCredentialWeb(
this,
await delegate.getRedirectResult(),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e);
}
@@ -297,20 +312,27 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
@override
Future<UserCredentialPlatform> signInAnonymously() async {
try {
return UserCredentialWeb(this, await delegate.signInAnonymously());
return UserCredentialWeb(
this,
await delegate.signInAnonymously(),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e);
throw getFirebaseAuthException(e, _webAuth);
}
}

@override
Future<UserCredentialPlatform> signInWithCredential(
AuthCredential credential) async {
AuthCredential credential,
) async {
try {
return UserCredentialWeb(
this,
await delegate
.signInWithCredential(convertPlatformCredential(credential)!));
this,
await delegate
.signInWithCredential(convertPlatformCredential(credential)!),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e, _webAuth);
}
@@ -320,7 +342,10 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
Future<UserCredentialPlatform> signInWithCustomToken(String token) async {
try {
return UserCredentialWeb(
this, await delegate.signInWithCustomToken(token));
this,
await delegate.signInWithCustomToken(token),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e, _webAuth);
}
@@ -331,7 +356,10 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
String email, String password) async {
try {
return UserCredentialWeb(
this, await delegate.signInWithEmailAndPassword(email, password));
this,
await delegate.signInWithEmailAndPassword(email, password),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e, _webAuth);
}
@@ -342,7 +370,10 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
String email, String emailLink) async {
try {
return UserCredentialWeb(
this, await delegate.signInWithEmailLink(email, emailLink));
this,
await delegate.signInWithEmailLink(email, emailLink),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e, _webAuth);
}
@@ -358,7 +389,10 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
auth_interop.RecaptchaVerifier verifier = applicationVerifier.delegate;

return ConfirmationResultWeb(
this, await delegate.signInWithPhoneNumber(phoneNumber, verifier));
this,
await delegate.signInWithPhoneNumber(phoneNumber, verifier),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e, _webAuth);
}
@@ -370,6 +404,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform {
return UserCredentialWeb(
this,
await delegate.signInWithPopup(convertPlatformAuthProvider(provider)),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e, _webAuth);
Original file line number Diff line number Diff line change
@@ -14,18 +14,25 @@ import 'utils/web_utils.dart';
/// The web delegate implementation for [ConfirmationResultPlatform].
class ConfirmationResultWeb extends ConfirmationResultPlatform {
/// Creates a new [ConfirmationResultWeb] instance.
ConfirmationResultWeb(this._auth, this._webConfirmationResult)
: super(_webConfirmationResult.verificationId);
ConfirmationResultWeb(
this._auth,
this._webConfirmationResult,
this._webAuth,
) : super(_webConfirmationResult.verificationId);

final FirebaseAuthPlatform _auth;

final auth_interop.ConfirmationResult _webConfirmationResult;
final auth_interop.Auth? _webAuth;

@override
Future<UserCredentialPlatform> confirm(String verificationCode) async {
try {
return UserCredentialWeb(
_auth, await _webConfirmationResult.confirm(verificationCode));
_auth,
await _webConfirmationResult.confirm(verificationCode),
_webAuth,
);
} catch (e) {
throw getFirebaseAuthException(e);
}
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import 'package:firebase_auth_web/firebase_auth_web.dart';
import 'package:firebase_auth_web/src/firebase_auth_web_user_credential.dart';

import 'interop/auth.dart' as auth;
import 'interop/auth.dart' as auth_interop;
import 'interop/multi_factor.dart' as multi_factor_interop;
import 'utils/web_utils.dart';

@@ -92,9 +93,11 @@ class MultiFactorResolverWeb extends MultiFactorResolverPlatform {
MultiFactorSession session,
this._auth,
this._webMultiFactorResolver,
this._webAuth,
) : super(hints, session);

final multi_factor_interop.MultiFactorResolver _webMultiFactorResolver;
final auth_interop.Auth? _webAuth;
final FirebaseAuthWeb _auth;

@override
@@ -106,6 +109,7 @@ class MultiFactorResolverWeb extends MultiFactorResolverPlatform {
return UserCredentialWeb(
_auth,
await _webMultiFactorResolver.resolveSignIn(webAssertion.assertion),
_webAuth,
);
}
}
Loading