简体   繁体   中英

Firebase Authentication with Google issue

I have been using Firebase Authentication in my app, and have noticed an issue with a particular use case.

I have enabled account linking sign up flow for my app, and thus I can attach multiple providers associated with a single email address.

Scenario 1: (Works fine)

The user has signed up with Google initially and sometime later, signs in in with Facebook or registers with email and password.

The account linking works fine and Facebook and/or Email is added in the provider list.

So, I can have 2 or 3 providers for the email, Google (initially), Facebook and Password (after that).

Scenario 2: (The bug)

The user has signed up with Facebook and/or Email initially and later signs in with Google, now the account linking doesn't work. Google replaces the previous providers present.

Account linking fails , and I just have Google as the sole provider associated with the email address and the others are gone.

In the second scenario, while signing in with Google , it should fail and throw FirebaseAuthCollisionException but it doesn't and succeeds. This is the main issue.

I can't paste the whole code here, but just a snippet for sure.

firebaseAuth
                        .signInWithCredential(credential)
                        .addOnFailureListener(exception -> {
                            if (exception instanceof FirebaseAuthUserCollisionException) {
                                mCredentialToLinkWith = credential;
                                if (mProviderList.size() == 1) {
                                    if (mProviderList.contains(EmailAuthProvider.PROVIDER_ID)) {
                                        mRegisterProviderPresenter.linkWithEmailProvider(credential, email);
                                    } else {
                                        linkProviderAccounts(email, AuthenticationHelper.getProviderToLinkAccounts(mWeakActivity, mProviderList));
                                    }
                                } else {
                                    linkProviderAccounts(email, AuthenticationHelper.getProviderToLinkAccounts(mWeakActivity, mProviderList));
                                }
                            } else {
                                Timber.d("Failed in signInWithCredential and unexpected exception %s", exception.getLocalizedMessage());
                                mRegisterProviderPresenter.onRegistrationFailed(new ErrorBundle(ErrorBundle.FIREBASE_ERROR, exception.getLocalizedMessage()));
                            }
                        })
                        .addOnSuccessListener(authResult -> {
                            Timber.d("Success: signInCred");
                            FirebaseUser firebaseUser = authResult.getUser();
                            /**
                             * Store the user details only for first time registration
                             * and not while acc linking
                             */
                            storeUserCredentials(firebaseUser);
                            AuthenticationHelper.logUserDetails(firebaseUser);
                            mRegisterProviderPresenter.onRegistrationSuccess(mAlreadyRegistered);

                        });

Hope someone can come up with some help.

Facebook is a social identity provider and it doesn't own the emails. If an email is hacked, Facebook can't detect it and disable the account registered by this email. While Google is an email provider, its accounts are considered to be more secure.

Based on this theory, scenario 2 is different from 1. In scenario 1, the user has proved the ownership of this email by signing with Google first. So the user is allowed to add Facebook account using the same email. In scenario 2, Facebook sign in happens first and this provider record is untrusted, so it's removed when user signs in with another trusted provider.

Your code behavior is correct in both scenarios.

I faced the same issue and this is a supplemental answer for the question in the comment ie

Why is that after initially registering with a email & password, and then with Google, Google still replaces it?

I did some more exploration and found the answer here .

Pasting the relevant snippet.

If there is an existing account with the same email address but created with non-trusted credentials (eg non-trusted provider or password), the previous credentials are removed for security reason. A phisher (who is not the email address owner) might create the initial account - removing the initial credential would prevent the phisher from accessing the account afterwards.

The solution to handle this, ie to prevent Google from replacing the existing provider with Google, is to verify the email of the user.

So, after the user creates the account with email & password, or logs in with Facebook (or any other provider), send an email verification link to the user.

After the user verifies his/her email, then the subsequent Sign-in with Google will NOT replace the existing providers.

暂时只使用电子邮件和密码身份验证或第 3 方插件目前尚无解决方案

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM