17

Jak rozumiem z Firebase Docs, jeśli użytkownik uwierzytelnia swoje konto poświadczeniem, powinien ściśle zalogować się, używając tego samego poświadczenia, jeśli poświadczenie nie jest powiązane z jeszcze jednym.Uwierzytelnianie za pomocą Facebooka na początku, a następnie Google powoduje błąd w Firebase dla Androida

Innymi słowy, jeśli utworzę konto za pomocą logowania Google, a następnie (po wylogowaniu) spróbuję zalogować się przy użyciu danych logowania na Facebooku za pomocą tego samego adresu e-mail, który jest używany do poświadczeń Google, powinienem zobaczyć ten wyjątek w logcat:

„konto już istnieje z tego samego adresu e-mail, ale różnych poświadczeń logowania się Zaloguj się przy użyciu dostawcy powiązanych z tym adresem e-mail.”.

I tak, otrzymuję ten wyjątek, co nie powinno dziwić. Ale jeśli założę konto za pomocą Facebooka, a następnie spróbuję zalogować się za pomocą danych logowania do Google, dostawca tego konta (Facebook) zostanie przekonwertowany na Google. Tym razem uwierzytelnianie nie zawiedzie, ale nie jest oczekiwanym rezultatem. Chcę powiązać każdego użytkownika z konkretnym poświadczeniem w pewien sposób. Jak mam to naprawić? Można zobaczyć poniższy kod:

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(); 
    } 
} 
+1

mam to samo, nie można znaleźć żadnego obejścia? – r3dm4n

+1

Zobacz odpowiedź bojeila. –

+0

Yup, sprawdziłem, ale myślałem, że może istnieć obejście. Na przykład, jeśli zezwolisz - wiele kont na adres e-mail - nie dostaniesz już tego, ale użytkownicy nie są połączeni w bazie danych. – r3dm4n

Odpowiedz

8

Proszę sprawdzić wątek: https://groups.google.com/forum/#!searchin/firebase-talk/liu/firebase-talk/ms_NVQem_Cw/8g7BFk1IAAAJ To wyjaśnia, dlaczego tak się dzieje. Wynika to z problemu bezpieczeństwa związanego z weryfikacją wiadomości e-mail od Google, podczas gdy wiadomości e-mail na Facebooku nie są.

+8

To naprawdę pachnie. Google automatycznie po cichu konwertuje konta na konta Google, ale nie robi tego samego na Facebooku i zamiast tego podaje błąd. Te bzdury "zaufanego dostawcy" są wymówką. Żaden użytkownik nie spodziewał się, że jego konto e-mail/hasło zostanie odebrane w milczeniu. Chcę, żeby były spójne. Google nie powinno cicho konwertować kont. Jak mogę zapobiec temu zachowaniu, gdy jestem w trybie "jedno konto na e-mail"? –

4

Aby zminimalizować liczbę kliknięć interfejsu użytkownika logowania bez uszczerbku dla bezpieczeństwa konta, usługa uwierzytelniania Firebase ma pojęcie "zaufanego dostawcy", w którym dostawca tożsamości jest również dostawcą usług poczty elektronicznej. Na przykład Google jest zaufanym dostawcą adresów @ gmail.com, Yahoo jest zaufanym dostawcą adresów @ yahoo.com i adresami Microsoft for @ outlook.com.

W trybie "Jedno konto na adres e-mail" uwierzytelnianie Firebase próbuje połączyć konto na podstawie adresu e-mail. Jeśli użytkownik loguje się od zaufanego dostawcy, użytkownik natychmiast loguje się do konta, ponieważ wiemy, że użytkownik jest właścicielem adresu e-mail.

Jeśli istnieje konto z tym samym adresem e-mail, ale utworzone z niezaufanymi danymi uwierzytelniającymi (np. Niezaufany dostawca lub hasło), poprzednie poświadczenia są usuwane ze względów bezpieczeństwa. Phisher (który nie jest właścicielem adresu e-mail) może utworzyć konto początkowe - usunięcie początkowego poświadczenia uniemożliwiłoby phisherowi dostęp do konta po nim.

Jin Liu

4

I skończyło się tej logiki:

Jeśli użytkownik spróbować zalogować się na Facebook'u, ale użytkownik o danym e-mail już istnieje (z dostawcą Google) i to Wystąpiły błędy:

"Konto już istnieje z tym samym adresem e-mail, ale różni się credo logowania Ntials. Zaloguj się przy użyciu dostawcy powiązanego z tym adresem e-mail: ."

Więc, po prostu zapytać użytkownika do zakładania konta przy użyciu Google (i po cichu odwołuje Facebooka do istniejącego konta)

Facebook and Google Sign In logics using firebase

-3

miałem ten sam problem, wszystko co musisz zrobić, to udać się do Firebase konsoli, a następnie w kategorii „autoryzacja” usunąć użytkownika, które chcesz.

który działa na mnie.

Powiązane problemy