in auth/src/main/java/com/firebase/ui/auth/viewmodel/idp/SocialProviderResponseHandler.java [47:127]
public void startSignIn(@NonNull final IdpResponse response) {
if (!response.isSuccessful() && !response.isRecoverableErrorResponse()) {
setResult(Resource.forFailure(response.getError()));
return;
}
if (isEmailOrPhoneProvider(response.getProviderType())) {
throw new IllegalStateException(
"This handler cannot be used with email or phone providers");
}
setResult(Resource.forLoading());
// Recoverable error flows (linking) for Generic OAuth providers are handled here.
// For Generic OAuth providers, the credential is set on the IdpResponse, as
// a credential made from the id token/access token cannot be used to sign-in.
if (response.hasCredentialForLinking()) {
handleGenericIdpLinkingFlow(response);
return;
}
final AuthCredential credential = ProviderUtils.getAuthCredential(response);
AuthOperationManager.getInstance().signInAndLinkWithCredential(
getAuth(),
getArguments(),
credential)
.continueWithTask(new ProfileMerger(response))
.addOnSuccessListener(result -> handleSuccess(response, result))
.addOnFailureListener(e -> {
// For some reason disabled users can hit FirebaseAuthUserCollisionException
// so we have to handle this special case.
boolean isDisabledUser = (e instanceof FirebaseAuthInvalidUserException);
if (e instanceof FirebaseAuthException) {
FirebaseAuthException authEx = (FirebaseAuthException) e;
FirebaseAuthError fae = FirebaseAuthError.fromException(authEx);
if (fae == FirebaseAuthError.ERROR_USER_DISABLED) {
isDisabledUser = true;
}
}
if (isDisabledUser) {
setResult(Resource.forFailure(
new FirebaseUiException(ErrorCodes.ERROR_USER_DISABLED)
));
} else if (e instanceof FirebaseAuthUserCollisionException) {
final String email = response.getEmail();
if (email == null) {
setResult(Resource.forFailure(e));
return;
}
// There can be a collision due to:
// CASE 1: Anon user signing in with a credential that belongs to an
// existing user.
// CASE 2: non - anon user signing in with a credential that does not
// belong to an existing user, but the email matches an existing user
// that has another social IDP. We need to link this new IDP to this
// existing user.
// CASE 3: CASE 2 with an anonymous user. We link the new IDP to the
// same account before handling invoking a merge failure.
ProviderUtils.fetchSortedProviders(getAuth(), getArguments(), email)
.addOnSuccessListener(providers -> {
if (providers.contains(response.getProviderType())) {
// Case 1
handleMergeFailure(credential);
} else if (providers.isEmpty()) {
setResult(Resource.forFailure(
new FirebaseUiException(
ErrorCodes.DEVELOPER_ERROR,
"No supported providers.")));
} else {
// Case 2 & 3 - we need to link
startWelcomeBackFlowForLinking(
providers.get(0), response);
}
})
.addOnFailureListener(e1 -> setResult(Resource.forFailure(
e1)));
}
});
}