Аутентификация с помощью Facebook сначала, а затем Google вызывает ошибку в Firebase для Android
Как я понимаю из Firebase Docs, если пользователь аутентифицирует свою учетную запись с помощью учетных данных, он должен строго войти в систему, используя те же учетные данные, если учетные данные еще не связаны с другим.
"учетная запись уже существует с тем же адресом электронной почты, но разные учетные данные для входа. Войдите с помощью поставщика, связанного с этим адрес электронной почты."
и да, я получаю это исключение, что неудивительно. Но если я создаю учетную запись с помощью Facebook, а затем пытаюсь войти с учетными данными Google, поставщик этой учетной записи (Facebook) преобразуется в Google. На этот раз проверка подлинности не завершается ошибкой, но это не ожидаемый результат. Я хочу связать каждого пользователя с конкретными учетными данными в некотором роде. Как это исправить? Вы можете увидеть код ниже:
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();
}
}
4 ответов
пожалуйста, проверьте поток: https://groups.google.com/forum/#!searchin/firebase-talk/liu/firebase-talk/ms_NVQem_Cw/8g7BFk1IAAAJ Это объясняет, почему это происходит. Это связано с некоторой проблемой безопасности с проверкой электронной почты Google, в то время как Facebook-нет.
чтобы свести к минимуму щелчки пользовательского интерфейса входа без ущерба для безопасности учетной записи, проверка подлинности Firebase имеет концепцию "доверенного поставщика", где поставщик удостоверений также является поставщиком услуг электронной почты. Например, Google является надежным поставщиком для @gmail.com адреса, Yahoo является надежным поставщиком для @yahoo.com адреса и Microsoft для @outlook.com адреса.
в режиме" одна учетная запись на адрес электронной почты " проверка подлинности Firebase пытается связать учетная запись на основе адреса электронной почты. Если пользователь входит в систему от доверенного поставщика, пользователь немедленно входит в учетную запись, так как мы знаем, что пользователь владеет адресом электронной почты.
если существует учетная запись с тем же адресом электронной почты, но созданная с ненадежными учетными данными (например, ненадежный поставщик или пароль), предыдущие учетные данные удаляются по соображениям безопасности. Фишер (который не является владельцем адреса электронной почты) может создать начальную учетную запись-удаление начальных учетных данных предотвратит доступ Фишера к учетной записи после этого.
Цзинь Лю
Я, наконец, закончил с этой логикой:
Если пользователь пытается войти в систему с Facebook, но пользователь с данной электронной почтой уже существует (с провайдером Google) , и это происходит ошибки:
"учетная запись уже существует с тем же адресом электронной почты, но разные учетные данные для входа. Войдите с помощью поставщика, связанного с этим адрес электронной почты."
Итак, просто попросите пользователя войти в систему с помощью Google (и после этого молча связать Facebook с существующим аккаунт)
У меня была та же проблема, все, что вам нужно сделать, это перейти к консоли Firebase, а затем в категории "аутентификация" удалить пользователя, которого вы хотите.
Это работает для меня.