diff --git a/packages/firebase_auth/firebase_auth/example/test_driver/instance_e2e.dart b/packages/firebase_auth/firebase_auth/example/test_driver/instance_e2e.dart index 52e6728d61cc..b25a26b2937a 100644 --- a/packages/firebase_auth/firebase_auth/example/test_driver/instance_e2e.dart +++ b/packages/firebase_auth/firebase_auth/example/test_driver/instance_e2e.dart @@ -193,8 +193,9 @@ void runInstanceTests() { try { await auth.applyActionCode('!!!!!!'); fail("Should have thrown"); - } on FirebaseException catch (e) { + } on FirebaseAuthException catch (e) { expect(e.code, equals("invalid-action-code")); + expect(e.status, AuthExceptionStatusCode.invalidActionCode); } catch (e) { fail(e.toString()); } @@ -206,8 +207,9 @@ void runInstanceTests() { try { await auth.checkActionCode('!!!!!!'); fail('Should have thrown'); - } on FirebaseException catch (e) { + } on FirebaseAuthException catch (e) { expect(e.code, equals("invalid-action-code")); + expect(e.status, AuthExceptionStatusCode.invalidActionCode); } catch (e) { fail(e.toString()); } @@ -220,8 +222,9 @@ void runInstanceTests() { await auth.confirmPasswordReset( code: '!!!!!!', newPassword: 'thingamajig'); fail('Should have thrown'); - } on FirebaseException catch (e) { + } on FirebaseAuthException catch (e) { expect(e.code, equals("invalid-action-code")); + expect(e.status, AuthExceptionStatusCode.invalidActionCode); } catch (e) { fail((e.toString())); } @@ -263,6 +266,7 @@ void runInstanceTests() { fail("Should have thrown FirebaseAuthException"); } on FirebaseAuthException catch (e) { expect(e.code, equals('email-already-in-use')); + expect(e.status, AuthExceptionStatusCode.emailAlreadyInUse); } catch (e) { fail(e.toString()); } @@ -276,6 +280,7 @@ void runInstanceTests() { fail("Should have thrown FirebaseAuthException"); } on FirebaseAuthException catch (e) { expect(e.code, equals('invalid-email')); + expect(e.status, AuthExceptionStatusCode.invalidEmail); } catch (e) { fail(e.toString()); } @@ -289,6 +294,7 @@ void runInstanceTests() { fail("Should have thrown FirebaseAuthException"); } on FirebaseAuthException catch (e) { expect(e.code, equals('weak-password')); + expect(e.status, AuthExceptionStatusCode.weakPassword); } catch (e) { fail(e.toString()); } @@ -315,7 +321,8 @@ void runInstanceTests() { await auth.fetchSignInMethodsForEmail('foobar'); fail('Should have thrown'); } on FirebaseAuthException catch (e) { - expect(e.code, equals("invalid-email")); + expect(e.code, equals('invalid-email')); + expect(e.status, AuthExceptionStatusCode.invalidEmail); } catch (e) { fail(e.toString()); } @@ -376,6 +383,7 @@ void runInstanceTests() { fail('Should have thrown'); } on FirebaseAuthException catch (e) { expect(e.code, equals('user-not-found')); + expect(e.status, AuthExceptionStatusCode.userNotFound); } catch (e) { fail(e.toString()); } @@ -720,7 +728,7 @@ void runInstanceTests() { Exception e = await getError(); expect(e, isA()); FirebaseAuthException exception = e as FirebaseAuthException; - expect(exception.code, equals('invalid-phone-number')); + expect(exception.status, AuthExceptionStatusCode.invalidPhoneNumber); }); test('should auto verify phone number', () async { diff --git a/packages/firebase_auth/firebase_auth/example/test_driver/test_utils.dart b/packages/firebase_auth/firebase_auth/example/test_driver/test_utils.dart index 7ee466decd38..fce25e2250a0 100644 --- a/packages/firebase_auth/firebase_auth/example/test_driver/test_utils.dart +++ b/packages/firebase_auth/firebase_auth/example/test_driver/test_utils.dart @@ -50,7 +50,7 @@ void ensureSignedIn(testEmail) async { await auth.createUserWithEmailAndPassword( email: testEmail, password: TEST_PASSWORD); } on FirebaseAuthException catch (e) { - if (e.code == 'email-already-in-use') { + if (e.status == AuthExceptionStatusCode.emailAlreadyInUse) { await auth.signInWithEmailAndPassword( email: testEmail, password: TEST_PASSWORD); } diff --git a/packages/firebase_auth/firebase_auth/example/test_driver/user_e2e.dart b/packages/firebase_auth/firebase_auth/example/test_driver/user_e2e.dart index 518e675bd8b8..482209e76059 100644 --- a/packages/firebase_auth/firebase_auth/example/test_driver/user_e2e.dart +++ b/packages/firebase_auth/firebase_auth/example/test_driver/user_e2e.dart @@ -126,7 +126,7 @@ void runUserTests() { )); } on FirebaseAuthException catch (e) { // Assertions - expect(e.code, 'email-already-in-use'); + expect(e.status, AuthExceptionStatusCode.emailAlreadyInUse); expect(e.message, 'The email address is already in use by another account.'); @@ -190,7 +190,7 @@ void runUserTests() { PhoneAuthProvider.credential( verificationId: 'test', smsCode: 'test')); } on FirebaseAuthException catch (e) { - expect(e.code, equals("invalid-verification-id")); + expect(e.status, AuthExceptionStatusCode.invalidVerificationId); expect( e.message, equals( @@ -239,7 +239,7 @@ void runUserTests() { await auth.currentUser.reauthenticateWithCredential(credential); } on FirebaseAuthException catch (e) { // Assertions - expect(e.code, equals("user-mismatch")); + expect(e.status, AuthExceptionStatusCode.userMismatch); expect( e.message, equals( @@ -293,7 +293,7 @@ void runUserTests() { await auth.currentUser.reauthenticateWithCredential(credential); } on FirebaseAuthException catch (e) { // Assertions - expect(e.code, equals("invalid-email")); + expect(e.status, AuthExceptionStatusCode.invalidEmail); expect(e.message, equals("The email address is badly formatted.")); return; } catch (e) { @@ -315,7 +315,7 @@ void runUserTests() { await auth.currentUser.reauthenticateWithCredential(credential); } on FirebaseAuthException catch (e) { // Assertions - expect(e.code, equals("wrong-password")); + expect(e.status, AuthExceptionStatusCode.wrongPassword); expect( e.message, equals( @@ -415,7 +415,7 @@ void runUserTests() { try { await auth.currentUser.unlink("invalid"); } on FirebaseAuthException catch (e) { - expect(e.code, 'no-such-provider'); + expect(e.status, AuthExceptionStatusCode.noSuchProvider); expect(e.message, 'User was not linked to an account with the given provider.'); return; @@ -433,7 +433,7 @@ void runUserTests() { try { await auth.currentUser.unlink(EmailAuthProvider.PROVIDER_ID); } on FirebaseAuthException catch (e) { - expect(e.code, 'no-such-provider'); + expect(e.status, AuthExceptionStatusCode.noSuchProvider); expect(e.message, 'User was not linked to an account with the given provider.'); return; @@ -488,7 +488,7 @@ void runUserTests() { // Update user password await auth.currentUser.updatePassword('weak'); } on FirebaseAuthException catch (e) { - expect(e.code, 'weak-password'); + expect(e.status, AuthExceptionStatusCode.weakPassword); expect(e.message, 'Password should be at least 6 characters'); return; } catch (e) { @@ -624,7 +624,7 @@ void runUserTests() { await auth.currentUser.updatePhoneNumber(PhoneAuthProvider.credential( verificationId: "invalid", smsCode: TEST_SMS_CODE)); } on FirebaseAuthException catch (e) { - expect(e.code, "invalid-verification-id"); + expect(e.status, AuthExceptionStatusCode.invalidVerificationId); expect(e.message, "The verification ID used to create the phone auth credential is invalid."); return; @@ -665,9 +665,10 @@ void runUserTests() { await auth.currentUser.updatePhoneNumber(PhoneAuthProvider.credential( verificationId: "", smsCode: TEST_SMS_CODE)); } on FirebaseAuthException catch (e) { - print(e.code); + // ignore: unnecessary_cast + print((e as FirebaseException).code); print(e.message); - expect(e.code, "invalid-verification-id"); + expect(e.status, AuthExceptionStatusCode.invalidVerificationId); expect(e.message, "The verification ID used to create the phone auth credential is invalid."); return; @@ -761,7 +762,7 @@ void runUserTests() { await user.delete(); } on FirebaseAuthException catch (e) { // Assertions - expect(e.code, 'no-current-user'); + expect(e.status, AuthExceptionStatusCode.noCurrentUser); expect(e.message, 'No user currently signed in.'); return; diff --git a/packages/firebase_auth/firebase_auth/lib/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/firebase_auth.dart index b781239ab0d2..35bb765c8797 100755 --- a/packages/firebase_auth/firebase_auth/lib/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/firebase_auth.dart @@ -47,7 +47,8 @@ export 'package:firebase_auth_platform_interface/firebase_auth_platform_interfac RecaptchaVerifierOnExpired, RecaptchaVerifierOnError, RecaptchaVerifierSize, - RecaptchaVerifierTheme; + RecaptchaVerifierTheme, + AuthExceptionStatusCode; export 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' show FirebaseException; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart index 3d9dbbdebdde..c1b14d036da3 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart @@ -11,6 +11,7 @@ export 'src/platform_interface/platform_interface_confirmation_result.dart'; export 'src/platform_interface/platform_interface_recaptcha_verifier_factory.dart'; export 'src/firebase_auth_exception.dart'; +export 'src/auth_exception_status_code.dart'; export 'src/auth_credential.dart'; export 'src/action_code_info.dart'; export 'src/action_code_settings.dart'; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/auth_exception_status_code.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/auth_exception_status_code.dart new file mode 100644 index 000000000000..f131b148f85c --- /dev/null +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/auth_exception_status_code.dart @@ -0,0 +1,90 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// The codes of the auth exceptions. +enum AuthExceptionStatusCode { + /// Thrown if the email address is not valid. + invalidEmail, + + /// Thrown if the user corresponding to the given email has been disabled. + userDisabled, + + /// Thrown if there is no user corresponding to the given email. + userNotFound, + + /// Thrown if the password is invalid for the given email, or the account corresponding to the email does not have a password set. + wrongPassword, + + /// Thrown if the Firebase Authentication quota is reached. + tooManyRequests, + + /// Thrown if specific auth provider is not enabled. + operationNotAllowed, + + /// Thrown if the email exists for multiple Firebase user's providers. + accountExistsWithDifferentCredential, + + /// Thrown if the request failed due to network issues. + networkRequestFailed, + + /// Thrown if a user being created already exists. + emailAlreadyInUse, + + /// Thrown if the request to create a user has a weak password. + weakPassword, + + /// Thrown if the phone verification fails with an invalid phone number. + invalidPhoneNumber, + + /// Thrown if the verification ID used to create the phone auth credential is invalid. + invalidVerificationId, + + /// Thrown if the supplied credentials do not correspond to the previously signed in user. + userMismatch, + + /// Thrown if the user does not have this provider linked or when the provider ID given does not exist. + noSuchProvider, + + /// Thrown if there is no user currently signed in. + noCurrentUser, + + /// Thrown if the supplied action code has expired. + expiredActionCode, + + /// Thrown if the supplied action code is not a valid format. + invalidActionCode, + + /// Thrown if the custom token is for a different Firebase App. + customTokenMismatch, + + /// Thrown if the custom token format is incorrect. + invalidCustomToken, + + /// Thrown if the credential is a [PhoneAuthProvider.credential] and the verification + /// code of the credential is not valid. + invalidVerificationCode, + + /// Thrown if the credential is malformed or has expired. + invalidCredential, + + /// if the user's last sign-in time does not meet the security threshold. + /// + /// Use [User.reauthenticateWithCredential] to resolve. This does not apply if the user is anonymous. + requiresRecentLogin, + + /// Thrown if the provider has already been linked to the user. + /// + /// This error is thrown even if this is not the same provider's account that is currently linked to the user. + providerAlreadyLinked, + + /// Thrown if the provider's credential is not valid. + /// + /// This can happen if it has already expired when calling link, or if it used + /// invalid token(s). See the Firebase documentation for your provider, and make + /// sure you pass in the correct parameters to the credential method. + credentialAlreadyInUse, + + /// Thrown if the status is unknown. + unknown, +} diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/firebase_auth_exception.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/firebase_auth_exception.dart index af7151505ece..270c7dbc2f96 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/firebase_auth_exception.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/firebase_auth_exception.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:firebase_auth_platform_interface/src/auth_exception_status_code.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:meta/meta.dart'; import 'auth_credential.dart'; @@ -20,7 +21,7 @@ class FirebaseAuthException extends FirebaseException implements Exception { this.tenantId}) : super(plugin: 'firebase_auth', message: message, code: code); - /// Unique error code + /// Unique error code. final String code; /// Complete error message. @@ -37,4 +38,61 @@ class FirebaseAuthException extends FirebaseException implements Exception { /// The tenant ID being used for sign-in/linking. final String tenantId; + + /// The error status code. + AuthExceptionStatusCode get status { + switch (super.code) { + case 'invalid-email': + return AuthExceptionStatusCode.invalidEmail; + case 'user-disabled': + return AuthExceptionStatusCode.userDisabled; + case 'user-not-found': + return AuthExceptionStatusCode.userNotFound; + case 'wrong-password': + return AuthExceptionStatusCode.wrongPassword; + case 'too-many-requests': + return AuthExceptionStatusCode.tooManyRequests; + case 'operation-not-allowed': + return AuthExceptionStatusCode.operationNotAllowed; + case 'account-exists-with-different-credential': + return AuthExceptionStatusCode.accountExistsWithDifferentCredential; + case 'network-request-failed': + return AuthExceptionStatusCode.networkRequestFailed; + case 'email-already-in-use': + return AuthExceptionStatusCode.emailAlreadyInUse; + case 'weak-password': + return AuthExceptionStatusCode.weakPassword; + case 'invalid-phone-number': + return AuthExceptionStatusCode.invalidPhoneNumber; + case 'invalid-verification-id': + return AuthExceptionStatusCode.invalidVerificationId; + case 'user-mismatch': + return AuthExceptionStatusCode.userMismatch; + case 'no-such-provider': + return AuthExceptionStatusCode.noSuchProvider; + case 'no-current-user': + return AuthExceptionStatusCode.noCurrentUser; + case 'expired-action-code': + return AuthExceptionStatusCode.expiredActionCode; + case 'invalid-action-code': + return AuthExceptionStatusCode.invalidActionCode; + case 'custom-token-mismatch': + return AuthExceptionStatusCode.customTokenMismatch; + case 'invalid-custom-token': + return AuthExceptionStatusCode.invalidCustomToken; + case 'invalid-verification-code': + return AuthExceptionStatusCode.invalidVerificationCode; + case 'invalid-credential': + return AuthExceptionStatusCode.invalidCredential; + case 'requires-recent-login': + return AuthExceptionStatusCode.requiresRecentLogin; + case 'provider-already-linked': + return AuthExceptionStatusCode.providerAlreadyLinked; + case 'credential-already-in-use': + return AuthExceptionStatusCode.credentialAlreadyInUse; + case 'unknown': + default: + return AuthExceptionStatusCode.unknown; + } + } } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart index 45323fe2844c..a69fa2ac23b4 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/utils/exception.dart'; @@ -52,7 +53,8 @@ void main() { FirebaseAuthException result = platformExceptionToFirebaseAuthException(platformException); - expect(result.code, equals('unknown')); + // ignore: unnecessary_cast + expect((result as FirebaseException).code, equals('unknown')); expect(result.message, equals('PlatformException Message')); expect(result.email, isNull); @@ -79,7 +81,8 @@ void main() { FirebaseAuthException result = platformExceptionToFirebaseAuthException(platformException); - expect(result.code, equals('A Known Code')); + // ignore: unnecessary_cast + expect((result as FirebaseException).code, equals('A Known Code')); expect(result.message, equals('A Known Message')); expect(result.email, 'test@email.com'); @@ -96,7 +99,8 @@ void main() { FirebaseAuthException result = platformExceptionToFirebaseAuthException(platformException); - expect(result.code, equals('unknown')); + // ignore: unnecessary_cast + expect((result as FirebaseException).code, equals('unknown')); expect(result.message, equals('a message')); expect(result.email, null); @@ -111,7 +115,8 @@ void main() { FirebaseAuthException result = platformExceptionToFirebaseAuthException(platformException); - expect(result.code, equals('unknown')); + // ignore: unnecessary_cast + expect((result as FirebaseException).code, equals('unknown')); expect(result.message, equals('a message')); expect(result.email, isNull); @@ -128,7 +133,8 @@ void main() { FirebaseAuthException result = platformExceptionToFirebaseAuthException(platformException); - expect(result.code, equals('A Known Code')); + // ignore: unnecessary_cast + expect((result as FirebaseException).code, equals('A Known Code')); expect(result.message, equals('A Known Message')); expect(result.email, 'test@email.com');