7
votes

I have implemented two step authentication in my app using firebase authentication in which I have used gmail, facebook or simple email login for authenticating. As digits phone verification has migrated to firebase i have implemented firebase phone authentication by linking the existing logged in account (facebook, gmail, or email) with phone authentication credentials. It works fine when used with facebook and email account. When user is logged in through google and tries to verify mobile through phone authentication this logs are printed :

signInWithCredential:failure

com.google.firebase.auth.FirebaseAuthUserCollisionException: An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.

Read this article. Is it the same issue as mentioned in the article?? Is there any solution for the same..

3

3 Answers

7
votes

After research over internet and in firebase documentation itself I found solution to this two step authentication in app using firebase auth.

firebaseAuth.getCurrentUser().updatePhoneNumber(credential).addOnCompleteListener(this, new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
            if (task.isSuccessful()) {
                Log.d(TAG, "signInWithCredential:success");

                Snackbar.make(findViewById(android.R.id.content), "Mobile Verified Successfully.",
                        Snackbar.LENGTH_SHORT).show();

            } else {
                Log.w(TAG, "signInWithCredential:failure", task.getException());
                if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                    //mVerificationField.setError("Invalid code.");
                    Snackbar.make(findViewById(android.R.id.content), "Invalid Code.",
                            Snackbar.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context,"signInWithCredential:failure"+task.getException(),
                            Snackbar.LENGTH_LONG).show();
                }
            }
        }
    });

Just pass the PhoneAuthCredential to above method and it will verify the phone assigns to your existing account. Make sure it is not used by any other account.

PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
1
votes

now phone auth is available in firebase.Here is Code for Phone Auth using Firebase: If there is any question fee free to ASK me.

EditText phoneNum,Code;           //// two edit text one for enter phone number other for enter OTP code
Button sent_,Verify;                    // sent_ button to request for verification and verify is for to verify code
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private FirebaseAuth mAuth;
private String mVerificationId;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_phone_number_auth);

    phoneNum =(EditText) findViewById(R.id.fn_num);
    Code =(EditText) findViewById(R.id.code);

    sent_ =(Button)findViewById(R.id.sent_nu);
    Verify =(Button)findViewById(R.id.verify);

    callback_verificvation();                                




    mAuth = FirebaseAuth.getInstance();



    sent_.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String num=phoneNum.getText().toString();
            startPhoneNumberVerification(num);                  // call function for receive OTP 6 digit code
        }
    });





    Verify.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String code=Code.getText().toString();
            verifyPhoneNumberWithCode(mVerificationId,code);                 //call function for verify code

        }
    });
}







private void startPhoneNumberVerification(String phoneNumber) {
    // [START start_phone_auth]
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            this,               // Activity (for callback binding)
            mCallbacks);        // OnVerificationStateChangedCallbacks
    // [END start_phone_auth]


}







private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information

                        FirebaseUser user = task.getResult().getUser();
                        Toast.makeText(getApplicationContext(), "sign in successfull", Toast.LENGTH_SHORT).show();
                        // [START_EXCLUDE]

                        // [END_EXCLUDE]
                    } else {
                        // Sign in failed, display a message and update the UI

                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                            // [START_EXCLUDE silent]

                            // [END_EXCLUDE]
                        }
                        // [START_EXCLUDE silent]
                        // Update UI

                        // [END_EXCLUDE]
                    }
                }
            });
}






private void verifyPhoneNumberWithCode(String verificationId, String code) {
    // [START verify_with_code]
    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
    // [END verify_with_code]
    signInWithPhoneAuthCredential(credential);
}










private void callback_verificvation() {

    mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        @Override
        public void onVerificationCompleted(PhoneAuthCredential credential) {

            signInWithPhoneAuthCredential(credential);
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            // This callback is invoked in an invalid request for verification is made,

        }

        @Override
        public void onCodeSent(String verificationId,
                               PhoneAuthProvider.ForceResendingToken token) {
            // The SMS verification code has been sent to the provided phone number, we
            // now need to ask the user to enter the code and then construct a credential
            // by combining the code with a verification ID.


            // Save verification ID and resending token so we can use them later
            mVerificationId = verificationId;
            mResendToken = token;

        }
    };
-1
votes

This Exception is thrown because you have connected the email pw login and facebook login together, the google account with same email used in facebook one's is not associated together. As by default, firebase doesn't allow multiple account from same email this collision occurs.

To solve this issue you have two options

1. Link the google account to the facebook and email one's using

mAuth.getCurrentUser().linkWithCredential(credential); 

Adding new credential to the existing logged in user.

2. Enable multiple account from same email(not recommended) from the firebase console

This will make new uid for the google logged user and the previous facebook login user will have the old one.