I have successfully deployed tutorial code from https://firebase.google.com/docs/auth/android/facebook-login for integrating Firebase Auth logins with Facebook. The users successfully created in Firebase Auth console.
However, I noticed that the Email field in the user object is empty (—). Strangely, I successfully retrieved the email information directly from provider result objects using GraphRequest using the acquired token.
Based on the documentation I read (https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseUser.html#getEmail()), the email field should be populated from login providers.
Some additional strange behaviour:
- After successful login, the onAuthStateChanged is called twice. The value of firebaseAuth.getCurrentUser().getProviderId() is Firebase on both occasion
- I try to list down the providers from the FirebaseUser object, user.getProviderData(). I got two providers: firebase and facebook.com
- When I tried to update email using FirebaseUser.updateEmail(event.getEmail()), I got this error: An internal error has occurred. [ EMAIL_EXISTS ]
Is there something I miss or did I do something wrong?
Here's my code:
public class LoginActivity extends AppCompatActivity { private static final String TAG = "LOGIN_ACTIVITY"; private static final int RC_SIGN_IN = 777; private EventBus eventBus; private SweetAlertDialog pDialog; private FirebaseAuth mAuth; private FirebaseAuth.AuthStateListener mAuthListener; private CallbackManager mCallbackManager; private ImageView mPasswordVisibilityView; private TextView txtPassword; private boolean justEnteredAuthStateChanged = false; private GoogleApiClient mGoogleApiClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FacebookSdk.sdkInitialize(getApplicationContext()); setContentView(R.layout.login); // Firebase mAuth = FirebaseAuth.getInstance(); mAuthListener = new FirebaseAuth.AuthStateListener() { @Override public void onAuthStateChanged(@NonNull final FirebaseAuth firebaseAuth) { final FirebaseUser user = firebaseAuth.getCurrentUser(); if (user != null) { // User is signed in Util.logassert("Auth Provider = " + firebaseAuth.getCurrentUser().getProviderId()); // this is called twice, values of Provider = Firebase Util.logassert("total provider = " + user.getProviderData().size()); // output = 2. "Firebase" and "facebook.com" for (int i = 0; i < user.getProviderData().size(); i++) { UserInfo info = user.getProviderData().get(i); Util.logassert(info.getProviderId() + ", email = " + info.getEmail()); // both empty Util.logassert("current provider = " + info.getProviderId() + " - " + info); } } else { Util.logassert("onAuthStateChanged user logged out"); } // ... } }; mAuth.addAuthStateListener(mAuthListener); // Firebase Facebook TapAuth // Initialize Facebook Login button mCallbackManager = CallbackManager.Factory.create(); LoginManager.getInstance().registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() { @Override public void onSuccess(LoginResult loginResult) { Util.logassert("facebook:onSuccess:" + loginResult); handleFacebookAccessToken(loginResult.getAccessToken()); Util.logassert("granted = " + loginResult.getRecentlyGrantedPermissions()); // output [email and public_profile] Util.logassert("denied = " + loginResult.getRecentlyDeniedPermissions()); } @Override public void onCancel() { Util.logassert("facebook:onCancel"); // ... } @Override public void onError(FacebookException error) { Util.logassert("facebook:onError" + error.getMessage()); // ... } }); FancyButton btnFacebook = (FancyButton) findViewById(R.id.btn_facebook_share); btnFacebook.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LoginManager.getInstance().logInWithReadPermissions(LoginActivity.this, Arrays.asList("public_profile", "email")); Util.logassert("try facebook login"); } }); txtPassword = (EditText) findViewById(R.id.input_password); } private void handleFacebookAccessToken(AccessToken token) { Util.logassert("handleFacebookAccessToken:" + token); GraphRequest request = GraphRequest.newMeRequest( token, new GraphRequest.GraphJSONObjectCallback() { @Override public void onCompleted( JSONObject object, GraphResponse response) { // Application code Log.v("LoginActivity", response.toString()); Util.logassert("graph res = " + response.getRawResponse()); try { /* successfully output email address from graph request here */ FbGraphEvent event = new FbGraphEvent(response.getJSONObject().getString("email"), response.getJSONObject().getString("name")); EventBus.getDefault().postSticky(event); } catch (Exception e) { Log.e("MomInvoice", "Error in parsing json fb graph", e); } } }); Bundle parameters = new Bundle(); parameters.putString("fields", "email,name"); request.setParameters(parameters); request.executeAsync(); AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken()); mAuth.signInWithCredential(credential) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { Util.logassert("signInWithCredential:onComplete:" + task.isSuccessful()); if (!task.isSuccessful()) { Util.logassert("signInWithCredential failed coz = " + task.getException().getMessage()); Toast.makeText(LoginActivity.this, "Authentication failed :(", Toast.LENGTH_SHORT).show(); } } }); } @Override public void onStart() { super.onStart(); Util.logassert("masuk onStart LoginActivity"); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { if (mAuthListener != null) { mAuth.removeAuthStateListener(mAuthListener); } super.onDestroy(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (mCallbackManager != null) { mCallbackManager.onActivityResult(requestCode, resultCode, data); Util.logassert("hasilx " + requestCode + " = " + resultCode); } } } 

error.userInfo.FIRAuthErrorUserInfoEmailKey