The Firebase Authentication SDKs provide a simple way for catching the various errors which may occur which using
authentication methods. The SDKs for Flutter expose these errors via the
FirebaseAuthException
class.
At a minimum, a
code
and
message
are provided, however in some cases additional properties such as an email address
and credential are also provided. For example, if the user is attempting to sign in with an email and password,
any errors thrown can be explicitly caught:
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen@example.com",
password: "SuperSecretPassword!"
);
} on FirebaseAuthException catch (e) {
print('Failed with error code: ${e.code}');
print(e.message);
}
Each method provides various error codes and messages depending on the type of authentication invocation type. The
Reference API
provides up-to-date details on the errors for each method.
Other errors such as
too-many-requests
or
operation-not-allowed
may be thrown if you reach the Firebase Authentication quota,
or have not enabled a specific auth provider.
Handling
account-exists-with-different-credential
Errors
If you enabled the One account per email address setting in the
Firebase console
,
when a user tries to sign in a to a provider (such as Google) with an email that already exists for another Firebase user's provider
(such as Facebook), the error
auth/account-exists-with-different-credential
is thrown along with an
AuthCredential
class (Google ID token).
To complete the sign-in flow to the intended provider, the user has to first sign in to the existing provider (e.g. Facebook) and then link to the former
AuthCredential
(Google ID token).
FirebaseAuth auth = FirebaseAuth.instance;
// Create a credential from a Google Sign-in Request
var googleAuthCredential = GoogleAuthProvider.credential(accessToken: 'xxxx');
try {
// Attempt to sign in the user in with Google
await auth.signInWithCredential(googleAuthCredential);
} on FirebaseAuthException catch (e) {
if (e.code == 'account-exists-with-different-credential') {
// The account already exists with a different credential
String email = e.email;
AuthCredential pendingCredential = e.credential;
// Fetch a list of what sign-in methods exist for the conflicting user
List<String> userSignInMethods = await auth.fetchSignInMethodsForEmail(email);
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
if (userSignInMethods.first == 'password') {
// Prompt the user to enter their password
String password = '...';
// Sign the user in to their account with the password
UserCredential userCredential = await auth.signInWithEmailAndPassword(
email: email,
password: password,
);
// Link the pending credential with the existing account
await userCredential.user.linkWithCredential(pendingCredential);
// Success! Go back to your application flow
return goToApplication();
}
// Since other providers are now external, you must now sign the user in with another
// auth provider, such as Facebook.
if (userSignInMethods.first == 'facebook.com') {
// Create a new Facebook credential
String accessToken = await triggerFacebookAuthentication();
var facebookAuthCredential = FacebookAuthProvider.credential(accessToken);
// Sign the user in with the credential
UserCredential userCredential = await auth.signInWithCredential(facebookAuthCredential);
// Link the pending credential with the existing account
await userCredential.user.linkWithCredential(pendingCredential);
// Success! Go back to your application flow
return goToApplication();
}
// Handle other OAuth providers...
}
}