【问题标题】:Firebase link email to phone: Cannot create PhoneAuthCredential without verificationProofFirebase 将电子邮件链接到电话:无法在没有验证证明的情况下创建 PhoneAuthCredential
【发布时间】:2019-05-01 09:37:07
【问题描述】:

所以自从我上周更新了我的 Firebase 后,我的电话验证就开始工作了。从那时起,我面临的问题是在我将用户电子邮件连接到电话号码的链接过程中不再起作用: java.lang.IllegalArgumentException:在没有验证证明、会话信息或临时证明的情况下无法创建 PhoneAuthCredential。 我见过一些用户遇到同样的问题,但没有人有解决方案。

我试图重写整个代码,但问题仍然存在。 Firebase 是否在链接过程中进行了某些更改? 正如我在 Firebase 链接文档中看到的那样,删除了有关电话号码链接的部分。

是我的代码有问题还是 firebase 有问题?

Firebase Versions I'm using:

implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.google.firebase:firebase-messaging:17.6.0'
implementation 'com.google.firebase:firebase-perf:16.2.5'
implementation 'com.android.support:support-compat:28.0.0'
implementation 'com.google.firebase:firebase-auth:16.2.1'
implementation 'com.google.firebase:firebase-storage:16.1.0'
   @Override
   protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.user_phone_verify);
   Log.e("PhoneVerify","Start");

        mAuth = FirebaseAuth.getInstance();

        editTextCode = findViewById(R.id.editTextCode);
        editTextPhone = findViewById(R.id.editTextPhone);

        Bundle extras = getIntent().getExtras();
        if (extras !=null) {
            final String phone = extras.getString("phone");
            Log.e("Phone(Extras):",phone);
            editTextPhone.setText(phone);
            sendVerificationCode(phone);
        }


        findViewById(R.id.buttonGetVerificationCode).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String phone = editTextPhone.getText().toString().trim();
                if (phone.isEmpty() || phone.length() < 10) {
                    editTextPhone.setError("Phone number error");
                    editTextPhone.requestFocus();
                    return;
                }

                 sendVerificationCode(phone);
            }
        });


        findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                verifyVerificationCode(editTextCode.getText().toString());
            }
        });
    }


    private void sendVerificationCode(String phonenumber) {
        String phone = "+14" + phonenumber;
        Log.e("sendVerificationCode",phone);
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phone,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);        // OnVerificationStateChangedCallbacks
    }



    PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        @Override
        public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {

             //Getting the code sent by SMS
            final String code = phoneAuthCredential.getSmsCode();

            if (code != null) {
                editTextCode.setText(code);
                //verifying the code
                verifyVerificationCode(code);
                Log.e("onVerificationCompleted",code);
            }

        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            Log.e("onVerificationFailed", String.valueOf(e));

        }

        @Override
        public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);
            Log.e("onCodeSent", "Code Sent");
            codeSent = s;
            PhoneAuthProvider.ForceResendingToken mResendToken = forceResendingToken;
        }
    };



    private void verifyVerificationCode(String code) {
        //creating the credential
        try {

            PhoneAuthCredential credential = PhoneAuthProvider.getCredential(codeSent, code);
            linkWithCredential(credential,code);

        } catch (Exception e) {
            Log.e("Exception", String.valueOf(e));
        }

        Log.e("VerifyCode CHECKP",code);
        //signing the user

    }

    private void linkWithCredential(final AuthCredential credential, final String code) {
        mAuth.getCurrentUser().linkWithCredential(credential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                Log.e("Linking Phone to Email","Successfull");

                try {

                    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(codeSent, code);
                    signInWithPhoneAuthCredential(credential);

                } catch (Exception e) {
                    Log.e("Exception", String.valueOf(e));
                }

            }
        });
    }


    private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(PhoneVerify.this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            //verification successful we will start the profile activity

                            Log.e("FINAL LINK","DONE");


                        } else {
                            //verification unsuccessful.. display an error message

                            String message = "Somthing is wrong, we will fix it soon...";



                });
    }



    }

【问题讨论】:

    标签: java android firebase firebase-authentication


    【解决方案1】:

    这里如何使用 Firebase 文档中的 Firebase 电话身份验证
    https://firebase.google.com/docs/auth/android/phone-auth
    并链接身份验证提供程序
    https://firebase.google.com/docs/auth/android/account-linking

    //please notice, mCallback.onVerificationCompleted will automatically called 
    //if verification code already send to your phone 
    //(Maybe not called in some case)
    mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
    
        @Override
        public void onVerificationCompleted(PhoneAuthCredential credential) {
            linkPhoneAuthToCurrentUser(credential);
        }
    
        @Override
        public void onVerificationFailed(FirebaseException e) {
            //show error
        }
        @Override
        public void onCodeSent(String verificationId,
                               PhoneAuthProvider.ForceResendingToken token) {
            //save id and token in case you need to resend verification code
        }
    };
    
    //call this to send verification code
    //parameter include country code
    private void sendVerificationCode(String phonenumber) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phonenumber,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);        // OnVerificationStateChangedCallbacks
    }
    
    //link auth with credential
    private void linkPhoneAuthToCurrentUser(PhoneAuthCredential credential) {
        FirebaseAuth.getInstance().getCurrentUser().linkWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        //link auth success update ui
                    } else {
                        //link auth failed update ui
                    }
                }
            });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.user_phone_verify);
    
       //init view 
    
       //get phone number
       String phoneNumb = "Add Your Phone Number Here"
       sendVerificationCode(phoneNumb)
    
       //if mCallback not called, 
       //use this button to sign in with manual input verification code
       btnSignIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //get verification id from mCallback.onCodeSent
                //get verificationCode manually from edittext 
                PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, verificationCode);
                linkPhoneAuthToCurrentUser(credential);
            }
        });
    }
    

    PS:您需要在链接电话号码认证之前重新认证您的电子邮件认证。
    点击此链接重新认证
    https://firebase.google.com/docs/auth/android/manage-users#re-authenticate_a_user

    【讨论】:

    • 谢谢您,先生,这是一个重要的答案!
    【解决方案2】:

    onVerificationCompleted在firebase通过检测发送到手机的短信代码自动验证电话号码时被调用。 我认为您应该重新格式化您的代码以仅使用此处的凭据,或者您通过用户输入的代码和verificationId的组合手动生成的凭据;而不是两者兼而有之。 也无需再次使用手机凭据登录,您已经登录了

    我的意思是你应该有这样的东西,

    private void linkWithCredential(final PhoneAuthCredential credential) {
            mAuth.getCurrentUser().linkWithCredential(credential).addOnComplete.......{
                onComplete(....) {
                    .....
                    //signInWithPhoneCredential(credential);
                    // You Already signed in. No need. Just update the ui with the user info
        }
    

    https://firebase.google.com/docs/auth/android/account-linking

    【讨论】:

    • 所以基本上 linkWithCredential 也是 signInWithPhoneAuthCredential 吗?
    猜你喜欢
    • 2019-05-28
    • 1970-01-01
    • 2020-12-03
    • 2019-05-20
    • 1970-01-01
    • 2020-11-02
    • 2020-03-07
    • 2018-06-19
    • 1970-01-01
    相关资源
    最近更新 更多