17

Khi tôi hiểu từ Firebase Docs, nếu người dùng xác thực tài khoản của mình bằng thông tin đăng nhập, anh ấy phải đăng nhập nghiêm ngặt bằng cách sử dụng cùng một thông tin xác thực với một cái khác.Xác thực bằng Facebook lúc đầu và sau đó Google gây ra lỗi trong Firebase cho Android

Nói cách khác, nếu tôi tạo tài khoản bằng cách sử dụng đăng nhập Google, sau đó (sau khi đăng xuất), hãy thử đăng nhập bằng thông tin đăng nhập Facebook bằng cách sử dụng cùng một email được sử dụng cho thông tin xác thực của Google, tôi sẽ thấy ngoại lệ này logcat:

"tài khoản đã tồn tại với địa chỉ email tương tự nhưng khác nhau thông tin đăng nhập Đăng nhập sử dụng một nhà cung cấp liên quan đến địa chỉ email này .."

Và có, tôi nhận được ngoại lệ này không đáng ngạc nhiên. Nhưng nếu tôi tạo một tài khoản bằng cách sử dụng Facebook, và sau đó cố gắng đăng nhập bằng chứng chỉ Google, nhà cung cấp tài khoản này (Facebook) sẽ được chuyển đổi sang Google. Xác thực thời gian này không thành công nhưng không phải là kết quả mong đợi. Tôi muốn kết hợp từng người dùng với một chứng chỉ cụ thể theo cách. Làm thế nào tôi nên sửa lỗi này? Bạn có thể xem mã bên dưới:

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

tôi nhận được điều tương tự, bạn đã tìm thấy bất kỳ cách giải quyết? – r3dm4n

+1

Xin vui lòng xem câu trả lời của bojeil. –

+0

Yup, đã kiểm tra điều đó, nhưng tôi nghĩ có thể có một cách giải quyết khác. Ví dụ: nếu bạn cho phép - nhiều tài khoản trên mỗi địa chỉ email - bạn không nhận được điều này nữa, nhưng người dùng không được liên kết trong cơ sở dữ liệu. – r3dm4n

Trả lời

8

Vui lòng kiểm tra các chủ đề: https://groups.google.com/forum/#!searchin/firebase-talk/liu/firebase-talk/ms_NVQem_Cw/8g7BFk1IAAAJ Nó giải thích lý do tại sao điều này xảy ra. Điều này là do một số vấn đề bảo mật với email của Google được xác minh trong khi email Facebook thì không.

+8

Điều này thực sự có mùi. Google tự động chuyển đổi tài khoản sang tài khoản Google, nhưng không thực hiện tương tự cho Facebook và thay vào đó đưa ra một lỗi. Điều này "nhà cung cấp đáng tin cậy" vô nghĩa là một cái cớ. Không người dùng nào mong đợi tài khoản email/mật khẩu của họ bị thu hồi âm thầm. Tôi muốn họ nhất quán. Google không được chuyển đổi âm thầm tài khoản. Làm cách nào để ngăn chặn hành vi này khi tôi đang ở chế độ "một tài khoản trên mỗi email"? –

4

Để giảm thiểu số lần nhấp vào giao diện người dùng đăng nhập mà không ảnh hưởng đến bảo mật tài khoản, Xác thực Firebase có khái niệm 'nhà cung cấp đáng tin cậy', nơi nhà cung cấp nhận dạng cũng là nhà cung cấp dịch vụ email. Ví dụ: Google là nhà cung cấp đáng tin cậy cho địa chỉ @ gmail.com, Yahoo là nhà cung cấp đáng tin cậy cho địa chỉ @ yahoo.com và địa chỉ Microsoft cho @ outlook.com.

Trong chế độ "Một tài khoản cho mỗi địa chỉ email", Xác thực Firebase cố liên kết tài khoản dựa trên địa chỉ email. Nếu người dùng đăng nhập từ nhà cung cấp đáng tin cậy, người dùng ngay lập tức đăng nhập vào tài khoản vì chúng tôi biết người dùng sở hữu địa chỉ email.

Nếu có tài khoản hiện tại có cùng địa chỉ email nhưng được tạo bằng thông tin đăng nhập không đáng tin cậy (ví dụ: nhà cung cấp hoặc mật khẩu không đáng tin cậy), thông tin đăng nhập trước đó sẽ bị xóa vì lý do bảo mật. Người đánh lừa (người không phải là chủ sở hữu địa chỉ email) có thể tạo tài khoản ban đầu - xóa thông tin đăng nhập ban đầu sẽ ngăn chặn kẻ lừa đảo truy cập vào tài khoản sau đó.

Jin Liu

4

cuối cùng tôi đã kết thúc với logic này:

Nếu người dùng cố gắng đăng nhập bằng Facebook, nhưng người dùng với email cho đã tồn tại (với nhà cung cấp Google) và điều này lỗi occures:

"Tài khoản đã tồn tại với cùng một địa chỉ email nhưng khác nhau đăng nhập bằng crede ntials. Đăng nhập bằng nhà cung cấp được liên kết với địa chỉ email này."

Vì vậy, chỉ cần hỏi người sử dụng để loging sử dụng Google (và sau đó âm thầm liên kết Facebook vào tài khoản hiện có)

Facebook and Google Sign In logics using firebase

-3

tôi đã cùng một vấn đề, tất cả các bạn phải làm là đi đến căn cứ hỏa lực Console và sau đó trong "xác thực" mục xóa người dùng mà bạn muốn.

đó làm việc với tôi.

Các vấn đề liên quan