with sesion inicio google example con auth autenticar android firebase facebook-login firebase-authentication google-authentication

android - sesion - firebase login example



La autenticación usando Facebook al principio y luego Google causa un error en Firebase para Android (6)

Según tengo entendido por Firebase Docs , si un usuario autentica su cuenta con una credencial, debe iniciar sesión estrictamente usando la misma credencial si la credencial aún no está vinculada con otra.

En otras palabras, si creo una cuenta usando el inicio de sesión de Google y luego (después de cerrar sesión) intento iniciar sesión con la credencial de Facebook usando el mismo correo electrónico que se usa para la credencial de Google, debería ver esta excepción en logcat:

"Ya existe una cuenta con la misma dirección de correo electrónico pero con credenciales de inicio de sesión diferentes. Inicie sesión con un proveedor asociado con esta dirección de correo electrónico".

Y sí, me sorprende esta excepción. Pero si creo una cuenta usando Facebook y luego intento iniciar sesión con la credencial de Google, el proveedor de esta cuenta (Facebook) se convierte a Google. Esta vez, la autenticación no falla pero no es el resultado esperado. Quiero asociar a cada usuario con una credencial específica de alguna manera. ¿Cómo debo arreglar esto? Puedes ver el código a continuación:

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


Para minimizar los clics de la interfaz de usuario de inicio de sesión sin comprometer la seguridad de la cuenta, Firebase Authentication tiene un concepto de ''proveedor de confianza'', donde el proveedor de identidad también es el proveedor de servicios de correo electrónico. Por ejemplo, Google es el proveedor confiable para las direcciones @ gmail.com, Yahoo es el proveedor confiable para las direcciones @ yahoo.com y Microsoft para las direcciones @ outlook.com.

En el modo "Una cuenta por dirección de correo electrónico", Firebase Authentication intenta vincular la cuenta en función de la dirección de correo electrónico. Si un usuario inicia sesión desde un proveedor de confianza, el usuario inicia sesión inmediatamente en la cuenta ya que sabemos que el usuario posee la dirección de correo electrónico.

Si hay una cuenta existente con la misma dirección de correo electrónico pero creada con credenciales no confiables (por ejemplo, proveedor o contraseña no confiables), las credenciales anteriores se eliminan por razones de seguridad. Un phisher (que no es el propietario de la dirección de correo electrónico) podría crear la cuenta inicial; eliminar la credencial inicial evitaría que el phisher acceda a la cuenta posteriormente.

Jin Liu



Finalmente terminé con esta lógica:

Si el usuario intenta iniciar sesión con Facebook, pero el usuario con un correo electrónico dado ya existe (con el proveedor de Google) y se produce este error:

"Ya existe una cuenta con la misma dirección de correo electrónico pero con credenciales de inicio de sesión diferentes. Inicie sesión con un proveedor asociado con esta dirección de correo electrónico".

Por lo tanto, solo pídale al usuario que inicie sesión con Google (y luego enlace silenciosamente Facebook a la cuenta existente)


Permitir la creación de varias cuentas con la misma dirección de correo electrónico es lo que está buscando.

Eso funciona bien SOLO si revisas el correo electrónico en tu backend y esa es la referencia para tus usuarios. Si usa el ID de Firebase, eso no permitirá mantener usuarios únicos.


Permitir la creación de varias cuentas con la misma dirección de correo electrónico es lo que está buscando.


Tuve el mismo problema, todo lo que tienes que hacer es ir a Firebase Console y luego, en la categoría "Autenticación", eliminar el usuario que deseas.

Eso me funciona.