17

Firebase Docsからわかるように、ユーザーがアカウント情報を認証すると、信任状がリンクされていない場合は、まだ別のものと一緒に。最初にFacebookを使用して認証してから、Android用のFirebaseでエラーが発生する

つまり、Googleのサインインを使用してアカウントを作成してからサインアウトした後で、Googleの資格情報と同じメールを使用してFacebookの資格情報でログインしようとすると、 logcat:

「アカウントが既に同じメールアドレスが異なる サインイン資格情報で存在するこの メールアドレスに関連付けられているプロバイダを使用してサインイン。。」

はい、私はこの例外を驚くほどに得ています。しかし、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(); 
    } 
} 
+1

私は同じことを得るには、何か回避策を見つけましたか? – r3dm4n

+1

bojeilの答えをご覧ください。 –

+0

うん、それをチェックしたが、回避策があると思った。たとえば、電子メールアドレスごとに複数のアカウントを許可した場合、これ以上取得することはできませんが、ユーザーはデータベースにリンクされません。 – r3dm4n

答えて

8

がスレッドを確認してください:あなたは以下のコードを見ることができますhttps://groups.google.com/forum/#!searchin/firebase-talk/liu/firebase-talk/ms_NVQem_Cw/8g7BFk1IAAAJ それは、この問題が発生した理由を説明します。これは、Facebookの電子メールは確認されていないが、Googleの電子メールが検証されていることによるセキュリティ上の問題が原因です。

+8

これは本当に匂いがする。 Googleは自動的にアカウントをGoogleアカウントに自動的に変換しますが、Facebookでは同じことを行わず、代わりにエラーが発生します。この「信頼できるプロバイダ」ナンセンスは言い訳です。ユーザーは、電子メール/パスワードのアカウントが黙って取り消されるとは思っていません。私は彼らに一貫性を持たせたい。 Googleは黙ってアカウントを変換しないでください。 「メールごとに1つのアカウント」モードでこの動作を防止するにはどうすればよいですか? –

4

アカウントのセキュリティを損なうことなくログインUIのクリックを最小限に抑えるため、Firebase認証には「信頼できるプロバイダ」の概念があります。アイデンティティプロバイダは電子メールサービスプロバイダです。たとえば、Googleは@ gmail.comアドレスの信頼できるプロバイダであり、Yahooは@ yahoo.comアドレスの信頼できるプロバイダであり、Microsoftは@ outlook.comアドレスの信頼できるプロバイダです。

「電子メールアドレスごとに1つのアカウント」モードでは、Firebase認証は電子メールアドレスに基づいてアカウントをリンクしようとします。ユーザーが信頼できるプロバイダからログインした場合、ユーザーは電子メールアドレスを所有していることがわかっているので、すぐにアカウントにサインインします。

同じ電子メールアドレスを持つアカウントが存在し、信頼されていない資格情報(信頼されていないプロバイダやパスワードなど)で作成されている場合、セキュリティ上の理由から以前の資格情報は削除されます。フィッシャー(電子メールアドレスの所有者ではない)が初期アカウントを作成する可能性があります。最初のクレデンシャルを削除すると、フィッシャーがアカウントにアクセスできなくなります。

私は最終的にこのロジックで終わった

4

ジン劉:

ユーザーは、Facebookのアカウントでログインしようとしますが、指定したメールを持つユーザーが既に(Googleのプロバイダで)存在する場合、これエラーが発生します:

「同じメールアドレスでアカウントは既に存在しますが、異なる サインインクレイド訴訟この 電子メールアドレスに関連付けられたプロバイダを使用してログインします。「

だから、

、Googleだけを使用してlogingにユーザーを尋ねる(と、それは静かに既存のアカウントにFacebookを利用してリンクした後)

Facebook and Google Sign In logics using firebase

-3

私は同じ問題を抱えていた、すべてあなたがしなければならないに行くれますFirebaseコンソールとし、「認証」カテゴリにしたいユーザーを削除します。

私に動作します。

関連する問題