Muhammad Rayhan Muhammad Rayhan - 18 days ago 9
Android Question

Empty email field of Firebase Auth User using Facebook Login Integration (Firebase 3.0)

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:


  1. After successful login, the onAuthStateChanged is called twice. The
    value of firebaseAuth.getCurrentUser().getProviderId() is Firebase
    on both occasion

  2. I try to list down the providers from the FirebaseUser object, user.getProviderData(). I got two providers: firebase and facebook.com

  3. 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);
}

}
}

Answer

after reading post in firebase-talk google group here https://groups.google.com/forum/#!topic/firebase-talk/gPGNq-IkTLo, I found out the answer. The issue was happened because I'm using "Allow creation of multiple accounts with the same email address" in Firebase Auth sign-in method.

So I change the option into: "Prevent creation of multiple accounts with the same email address" can it's working properly now. It's simple as that. It's true I need more logic to merge accounts having the same email address, but it's okay.

Maybe everyone else having the same issue, can also try this, and hopefully it's solved as well.

Comments