in auth/src/main/java/com/firebase/ui/auth/viewmodel/idp/LinkingSocialProviderResponseHandler.java [44:123]
public void startSignIn(@NonNull final IdpResponse response) {
if (!response.isSuccessful()) {
setResult(Resource.forFailure(response.getError()));
return;
}
if (isInvalidProvider(response.getProviderType())) {
throw new IllegalStateException(
"This handler cannot be used to link email or phone providers.");
}
if (mEmail != null && !mEmail.equals(response.getEmail())) {
setResult(Resource.forFailure(new FirebaseUiException
(ErrorCodes.EMAIL_MISMATCH_ERROR)));
return;
}
setResult(Resource.forLoading());
// The Generic IDP flow does not return a credential - it signs us in right away.
// If the user was prompted to sign-in via Generic IDP, we can link immediately.
// Example: Existing user with Yahoo provider - signs in with microsoft -
// prompted to sign in with yahoo. Sign in with Yahoo will be succesful, it won't
// return a credential.
if (isGenericIdpLinkingFlow(response.getProviderType())) {
getAuth().getCurrentUser()
.linkWithCredential(mRequestedSignInCredential)
.addOnSuccessListener(authResult -> handleSuccess(response, authResult))
.addOnFailureListener(e -> Resource.<IdpResponse>forFailure(e));
return;
}
final AuthOperationManager authOperationManager = AuthOperationManager.getInstance();
final AuthCredential credential = ProviderUtils.getAuthCredential(response);
if (authOperationManager.canUpgradeAnonymous(getAuth(), getArguments())) {
if (mRequestedSignInCredential == null) {
// The user has provided a valid credential by signing in with a federated
// idp. linkWithCredential will fail because the user is anonymous and the account
// exists (we're in the welcome back flow).
// We know that they are signing in with the same IDP because requestSignInCredential
// is null.
// We just need to have the developer handle the merge failure.
handleMergeFailure(credential);
} else {
// The user has logged in with an IDP that has the same email with another IDP
// present on the account.
// These IDPs belong to the same account - they must be linked, but we can't lose
// our anonymous user session
authOperationManager.safeLink(credential, mRequestedSignInCredential, getArguments())
.addOnSuccessListener(result -> handleMergeFailure(credential))
.addOnFailureListener(e -> setResult(Resource.forFailure(e)));
}
} else {
getAuth().signInWithCredential(credential)
.continueWithTask(task -> {
final AuthResult result = task.getResult();
if (mRequestedSignInCredential == null) {
return Tasks.forResult(result);
} else {
return result.getUser()
.linkWithCredential(mRequestedSignInCredential)
.continueWith(task1 -> {
if (task1.isSuccessful()) {
return task1.getResult();
} else {
// Since we've already signed in, it's too late
// to backtrack so we just ignore any errors.
return result;
}
});
}
})
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
handleSuccess(response, task.getResult());
} else {
setResult(Resource.forFailure(task.getException()));
}
});
}
}