Firebase Authentication in Jetpack Compose

Handle Firebase Authentication Errors

Learn how to handle Firebase Auth Errors when working and Firebase Authentication

Marwa Diab
4 min readDec 11, 2023
Photo by Jexo on Unsplash

In the previous parts of this series, we implemented

Handle Auth Errors

Let’s look at some of the errors that needs to be handled when you have anonymous and multiple providers authentication.

Scenario 1

The user signed-in and out using one of the providers, then the user skipped the login process (i.e. anonymously authenticated), in this case two Firebase auth users will be created, one user with the signed-in provider, and the other user is anonymous.
The user can also be signed-in from a device, and skipped login on another device.

In the screenshot below, the user is authenticated using Apple provider from the iOS app for this project..

Authenticated Firebase users (Anonymous and Apple).

Scenario 2

The user already signed-in using a provider, and then you try to link accounts using another providers (which is already linked).

In this tutorial series, Scenario 2 was already handled, and so it won’t happen, but it could happen if you have the option of linking different providers in your app settings, so in order to test this scenario, comment the code inside onClick callback block of the sign-out button and just leave openLoginDialog.value = true, to show LoginScreen.

onClick = {
// if (authState != AuthState.SignedIn)
openLoginDialog.value = true
// else
// authViewModel.signOut()
},

Solution

authenticateUser(credentials:) function inside AuthRepositoryImpl we checked if the current firebase user is not null, then link account, otherwise sign-in (as explained in Part 1: Anonymous Authentication).

In scenario 1, if the user is anonymously authenticated and you are trying to link the anonymous account with a credential that is already in use (if you’re trying to link with the same provider) or email address is used by another account (if you’re trying to link with different provider), so link(with:) will throw one of these errors:

  • FirebaseAuthException: "ERROR_CREDENTIAL_ALREADY_IN_USE": Indicates an attempt to link with a credential that has already been linked with a different Firebase account.
  • FirebaseAuthException: "ERROR_EMAIL_ALREADY_IN_USE": Indicates the email asserted by the credential is already in use by an existing account.

In scenario 2, if the user is authenticated with Google, and you are trying to link the account also with the Google credentials, so link(with:) will throw the following error:

  • FirebaseException: "User has already been linked to the given provider.": Indicates an attempt to link a provider to which the account is already linked.

In these cases, switch to signIn(credential:) instead, as follows:

Scenario 1 solution:

Add another catch block in authLink(credentials:) that catches the FirebaseAuthException errors to check the error code.

catch (error: FirebaseAuthException) {
when (error.errorCode) {
"ERROR_CREDENTIAL_ALREADY_IN_USE",
"ERROR_EMAIL_ALREADY_IN_USE" -> {
Log.e(TAG, "FirebaseAuthError: authLink(credential:) failed, ${error.message}")
return authSignIn(credential)
}
}
Response.Failure(error)
}

Scenario 2 solution

  1. First solution is to prevent this from happening by checking on auth state as done before in onClick callback block inside sign-out button, and to hide sign-in whenever the user is authenticated with any provider.
  2. Second solution is to add another catch block that catches the FirebaseException errors and check if the error message contains the following message. (using the FirebaseException is optional, you can use Exception as well because in this case we check the error message not error code!)
catch (error: FirebaseException) {
error.message?.let {
if (it.contains("User has already been linked to the given provider" )) {
return authSignIn(credential)
}
}
Log.e(TAG, "FirebaseError: authLink(credential:) failed, ${error.message}")
Response.Failure(error)
}

Be aware that now you don’t have any reference to the anonymous account anymore, if you have associated data (e.g. Firestore) that uses the data from firebase auth user, it’s recommended to migrate or merge data between accounts.

--

--