首先使用Facebook进行身份验证,然后Google会在Android版Firebase中导致错误 [英] Authentication using Facebook at first and then Google causes an error in Firebase for Android

查看:530
本文介绍了首先使用Facebook进行身份验证,然后Google会在Android版Firebase中导致错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解,从 Firebase文档,如果用户使用凭证验证其帐户,他应该严格使用相同的凭证登录,如果凭证还没有链接到另一个。



换句话说,如果我使用Google登录创建帐户,然后(注销后)尝试使用用于Google凭证的相同电子邮件登录Facebook凭证,我应该在logcat中看到此异常:


一个帐户已经存在,但是使用相同的电子邮件地址,但是有不同的
登录凭据,请使用与此
电子邮件地址相关的提供商登录。


是的,我得到这个异常毫不奇怪。但是,如果我使用Facebook创建帐户,然后尝试使用Google凭据登录,则此帐户(Facebook)的提供者将转换为Google。这次认证不会失败,但不是预期的结果。我想以某种方式将每个用户与特定的凭证相关联。我应该如何解决这个问题?你可以看到下面的代码:

$ $ p $ public class SignInActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {

private static final String TAG =SignInActivity;
private static final int RC_SIGN_IN = 9001;

私有GoogleApiClient mGoogleApiClient;
私人FirebaseAuth mFirebaseAuth;
私人FirebaseAuth.AuthStateListener mFirebaseAuthListener;

私人CallbackManager mCallbackManager;

@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_sign_in);

// Facebook登录
FacebookSdk.sdkInitialize(getApplicationContext());
mCallbackManager = CallbackManager.Factory.create();

LoginButton mFacebookSignInButton =(LoginButton)findViewById(R.id.facebook_login_button);
mFacebookSignInButton.setReadPermissions(email,public_profile);

mFacebookSignInButton.registerCallback(mCallbackManager,new FacebookCallback< LoginResult>(){
@Override
public void onSuccess(LoginResult loginResult){
Log.d(TAG, facebook:onSuccess:+ loginResult);
firebaseAuthWithFacebook(loginResult.getAccessToken());
}
$ b @Override
public void onCancel(){
Log.d(TAG,facebook:onCancel);
}

@Override
public void onError(FacebookException错误){
Log.d TAG,facebook:onError,错误);
}
});

// Google Sign-In
//分配字段
SignInButton mGoogleSignInButton =(SignInButton)findViewById(R.id.google_sign_in_button);

//设置点击监听器
mGoogleSignInButton.setOnClickListener(this);

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build ();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this / * FragmentActivity * /,this / * OnConnectionFailedListener * /)
.addApi(Auth.GOOGLE_SIGN_IN_API,gso)
.build();

//初始化FirebaseAuth
mFirebaseAuth = FirebaseAuth.getInstance();

mFirebaseAuthListener = new FirebaseAuth.AuthStateListener(){
@Override $ b $ public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth){
FirebaseUser user = firebaseAuth.getCurrentUser();
if(user!= null){
//用户登录
Log.d(TAG,onAuthStateChanged:signed_in:+ user.getUid());
} else {
//用户签出
Log.d(TAG,onAuthStateChanged:signed_out);
}
}
};


@Override
public void onStart(){
super.onStart();
mFirebaseAuth.addAuthStateListener(mFirebaseAuthListener);


@Override
public void onStop(){
super.onStop();
if(mFirebaseAuthListener!= null){
mFirebaseAuth.removeAuthStateListener(mFirebaseAuthListener);


$ b private void firebaseAuthWithGoogle(GoogleSignInAccount acct){
Log.d(TAG,firebaseAuthWithGooogle:+ acct.getId());
AuthCredential凭证= GoogleAuthProvider.getCredential(acct.getIdToken(),null);
mFirebaseAuth.signInWithCredential(凭证)
.addOnCompleteListener(this,new OnCompleteListener< AuthResult>(){
@Override
public void onComplete(@NonNull Task< AuthResult> task){
Log.d(TAG,signInWithCredential:onComplete:+ task.isSuccessful());

//如果登录失败,向用户显示一条消息,如果登录成功
// auth状态侦听器将被通知,逻辑来处理
//登录用户可以在侦听器中处理
if(!task.isSuccessful()){
Log.w(TAG,signInWithCredential,task.getException());
Toast.makeText(SignInActivity.this,Authentication failed。,
Toast.LENGTH_SHORT).show();
} else {
startActivity(new Intent(SignInActivity.this,MainActivity.class));
finish();
}
}
});


private void firebaseAuthWithFacebook(AccessToken token){
Log.d(TAG,handleFacebookAccessToken:+ token);

final AuthCredential凭证= FacebookAuthProvider.getCredential(token.getToken());
mFirebaseAuth.signInWithCredential(凭证)
.addOnCompleteListener(this,new OnCompleteListener< AuthResult>(){
@Override
public void onComplete(@NonNull Task< AuthResult> task){
Log.d(TAG,signInWithCredential:onComplete:+ task.isSuccessful());

//如果登录失败,向用户显示一条消息,如果登录成功
// auth状态侦听器将被通知,逻辑来处理
//登录用户可以在侦听器中处理
if(!task.isSuccessful()){
Log.w(TAG,signInWithCredential,task.getException());
Toast.makeText(SignInActivity.this,Authentication failed。,
Toast.LENGTH_SHORT).show();
}

else {
startActivity(new Intent(SignInActivity.this,MainActivity.class));
finish();
}
}
});

$ b $ * b $ b private void handleFirebaseAuthResult(AuthResult authResult){
if(authResult!= null){
//欢迎用户
FirebaseUser user = authResult.getUser();
Toast.makeText(this,Welcome+ user.getEmail(),Toast.LENGTH_SHORT).show();

//返回主活动
startActivity(new Intent(this,MainActivity.class));

$ b $ /

@Override
public void onClick(View v){
switch(v.getId()) {
case R.id.google_sign_in_button:
signIn();
break;
默认值:
return;



private void signIn(){
意图signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent,RC_SIGN_IN);

$ b @Override
public void onActivityResult(int requestCode,int resultCode,Intent data){
super.onActivityResult(requestCode,resultCode,data);

mCallbackManager.onActivityResult(requestCode,resultCode,data);

//从GoogleSignInApi.getSignInIntent(...)启动Intent返回的结果;
if(requestCode == RC_SIGN_IN){
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if(result.isSuccess()){
// Google登录成功后,使用Firebase进行身份验证
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuthWithGoogle(帐户);
} else {
// Google登录失败
Log.e(TAG,Google Sign In failed。);



@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult){
//发生了一个无法解析的错误和Google API(包括登录)将不会
//可用。
Log.d(TAG,onConnectionFailed:+ connectionResult);
Toast.makeText(这是Google Play服务错误,Toast.LENGTH_SHORT).show();


$ / code $ / pre

解决方案

检查线程: https:// groups .google.com / forum /#!searchin / firebase-talk / liu / firebase-talk / ms_NVQem_Cw / 8g7BFk1IAAAJ
这解释了为什么发生这种情况。这是由于一些安全问题,谷歌电子邮件被验证,而Facebook的电子邮件不是。


As I understand from the Firebase Docs, if a user authenticates his account with a credential, he should strictly login by using the same credential if the credential is not linked with another one yet.

In other words, if I create an account by using Google sign in, and then (after sign out) try to login with Facebook credential by using the same email that is used for Google credential, I should see this exception in logcat:

"An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address."

And yes, I get this exception unsurprisingly. But if I create an account by using Facebook, and then try to login with Google credential, the provider of this account (Facebook) is converted to Google. This time authentication does not fail but it is not the expected result. I want to associate each user with a specific credential in a way. How should I fix this? You can see the code below:

public class SignInActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,
        View.OnClickListener {

    private static final String TAG = "SignInActivity";
    private static final int RC_SIGN_IN = 9001;

    private GoogleApiClient mGoogleApiClient;
    private FirebaseAuth mFirebaseAuth;
    private FirebaseAuth.AuthStateListener mFirebaseAuthListener;

    private CallbackManager mCallbackManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_sign_in);

        // Facebook Login
        FacebookSdk.sdkInitialize(getApplicationContext());
        mCallbackManager = CallbackManager.Factory.create();

        LoginButton mFacebookSignInButton = (LoginButton) findViewById(R.id.facebook_login_button);
        mFacebookSignInButton.setReadPermissions("email", "public_profile");

        mFacebookSignInButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Log.d(TAG, "facebook:onSuccess:" + loginResult);
                firebaseAuthWithFacebook(loginResult.getAccessToken());
            }

            @Override
            public void onCancel() {
                Log.d(TAG, "facebook:onCancel");
            }

            @Override
            public void onError(FacebookException error) {
                Log.d(TAG, "facebook:onError", error);
            }
        });

        // Google Sign-In
        // Assign fields
        SignInButton mGoogleSignInButton = (SignInButton) findViewById(R.id.google_sign_in_button);

        // Set click listeners
        mGoogleSignInButton.setOnClickListener(this);

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();

        // Initialize FirebaseAuth
        mFirebaseAuth = FirebaseAuth.getInstance();

        mFirebaseAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                } else {
                    // User is signed out
                    Log.d(TAG, "onAuthStateChanged:signed_out");
                }
            }
        };
    }

    @Override
    public void onStart() {
        super.onStart();
        mFirebaseAuth.addAuthStateListener(mFirebaseAuthListener);
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mFirebaseAuthListener != null) {
            mFirebaseAuth.removeAuthStateListener(mFirebaseAuthListener);
        }
    }

    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
        Log.d(TAG, "firebaseAuthWithGooogle:" + acct.getId());
        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        mFirebaseAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

                        // If sign in fails, display a message to the user. If sign in succeeds
                        // the auth state listener will be notified and logic to handle the
                        // signed in user can be handled in the listener.
                        if (!task.isSuccessful()) {
                            Log.w(TAG, "signInWithCredential", task.getException());
                            Toast.makeText(SignInActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            startActivity(new Intent(SignInActivity.this, MainActivity.class));
                            finish();
                        }
                    }
                });
    }

    private void firebaseAuthWithFacebook(AccessToken token) {
        Log.d(TAG, "handleFacebookAccessToken:" + token);

        final AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        mFirebaseAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

                        // If sign in fails, display a message to the user. If sign in succeeds
                        // the auth state listener will be notified and logic to handle the
                        // signed in user can be handled in the listener.
                        if (!task.isSuccessful()) {
                            Log.w(TAG, "signInWithCredential", task.getException());
                            Toast.makeText(SignInActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                        }

                        else {
                            startActivity(new Intent(SignInActivity.this, MainActivity.class));
                            finish();
                        }
                    }
                });
    }

    /*
    private void handleFirebaseAuthResult(AuthResult authResult) {
        if (authResult != null) {
            // Welcome the user
            FirebaseUser user = authResult.getUser();
            Toast.makeText(this, "Welcome " + user.getEmail(), Toast.LENGTH_SHORT).show();

            // Go back to the main activity
            startActivity(new Intent(this, MainActivity.class));
        }
    }
    */

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.google_sign_in_button:
                signIn();
                break;
            default:
                return;
        }
    }

    private void signIn() {
        Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        mCallbackManager.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = result.getSignInAccount();
                firebaseAuthWithGoogle(account);
            } else {
                // Google Sign In failed
                Log.e(TAG, "Google Sign In failed.");
            }
        }
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        // An unresolvable error has occurred and Google APIs (including Sign-In) will not
        // be available.
        Log.d(TAG, "onConnectionFailed:" + connectionResult);
        Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show();
    }
}

解决方案

Please check the thread: https://groups.google.com/forum/#!searchin/firebase-talk/liu/firebase-talk/ms_NVQem_Cw/8g7BFk1IAAAJ It explains why this happens. This is due to some security issue with Google emails being verified whereas Facebook emails are not.

这篇关于首先使用Facebook进行身份验证,然后Google会在Android版Firebase中导致错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆