首先使用 Facebook 进行身份验证,然后使用 Google 进行身份验证会导致 Firebase for Android 出现错误 [英] Authentication using Facebook at first and then Google causes an error in Firebase for Android
问题描述
据我从 Firebase Docs 中了解到,如果用户使用凭据对其帐户进行身份验证,如果该凭据尚未与其他凭据关联,则应严格使用同一凭据登录.
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.
换句话说,如果我使用 Google 登录创建帐户,然后(退出后)尝试使用与 Google 凭据相同的电子邮件使用 Facebook 凭据登录,我应该在 logcat 中看到此异常:
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."
是的,我毫不奇怪地得到这个例外.但是,如果我使用 Facebook 创建帐户,然后尝试使用 Google 凭据登录,则此帐户的提供者 (Facebook) 将转换为 Google.这次认证没有失败,但不是预期的结果.我想以某种方式将每个用户与特定凭据相关联.我应该如何解决这个问题?你可以看到下面的代码:
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();
}
}
推荐答案
请查看线程:https://groups.google.com/forum/#!searchin/firebase-talk/liu/firebase-talk/ms_NVQem_Cw/8g7BFk1IAAAJ它解释了为什么会发生这种情况.这是因为 Google 电子邮件被验证存在一些安全问题,而 Facebook 电子邮件则没有.
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 进行身份验证会导致 Firebase for Android 出现错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!