androidfirebasefirebase-authenticationmultiple-accounts

Firebase - allow multiple users for email, how to get top level email


My app uses Firebase authentication with 2 providers: Facebook and Google. To allow users to create both Facebook and Google accounts with the same email, I went to Firebase console and checked an option to allow multiple acoounts for email address.

Now it works, but for Facebook, email is always null. How can I get top level email address (linked to multiple accounts) in case when user decides to login with Facebook. I don't want to link providers into one account, I want to keep "allow multiple accounts for one mail address" turned on.

Any ideas how to get mail address in this case?

[edit]

Initialization for Google and Facebook apis:

 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, this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();

        mAuth = FirebaseAuth.getInstance();

        mAuthListener = firebaseAuth ->
        {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null)
            {
                // User is signed in
                Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                String uuid = user.getUid();
                String mail = user.getEmail();

                currentUserUid = user.getUid();

                //Toast.makeText(LoginActivity.this, "Zalogowano. Email: " + user.getEmail() + " uid: " + user.getUid(),
                //        Toast.LENGTH_SHORT).show();

                if (!logout)
                {
                    List<? extends UserInfo> provider = user.getProviderData();
                    AuthSocial(user, currentLoginType); //if "allow multiple accounts for mail enabled, user.getEmail always returns null for Facebook, how to get correct top level email for "multi account" here?
                }
                else
                {
                    //mAuth.signOut();
                }

            }
            else
            {
                // User is signed out
                Log.d(TAG, "onAuthStateChanged:signed_out");
            }
        };

        // [START initialize_fblogin]
        // Initialize Facebook Login button


        mCallbackManager = CallbackManager.Factory.create();
        LoginButton loginButton = (LoginButton) findViewById(R.id.bt_go_facebook);
        loginButton.setReadPermissions("email", "public_profile");
        loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>()
        {


            @Override
            public void onSuccess(LoginResult loginResult)
            {
                Log.d(TAG, "facebook:onSuccess:" + loginResult);
                handleFacebookAccessToken(loginResult.getAccessToken());
                currentLoginType = "facebook";
            }

            @Override
            public void onCancel()
            {
                Log.d(TAG, "facebook:onCancel");
                // [START_EXCLUDE]
                //updateUI(null);
                // [END_EXCLUDE]
            }

            @Override
            public void onError(FacebookException error)
            {
                Log.d(TAG, "facebook:onError", error);
                // [START_EXCLUDE]
                //updateUI(null);
                // [END_EXCLUDE]
            }
        });
        // [END initialize_fblogin]

Solution

  • Because facebook allow users to sign-in only with a phone number there are cases in which users do not update their accounts with their email address. Unfortunately, in those cases you cannot have their emaill addresses at all. To solve this, you can use in stead of email address, the provided phone number or the unique Google/Facebook id.

    In order to get the email address from facebook profie, you need to use registerCallback method on the callbackManager object. Here is the code:

    CallbackManager callbackManager = CallbackManager.Factory.create();
    facebookLoginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
        @Override
        public void onSuccess(LoginResult loginResult) {
            AccessToken accessToken = loginResult.getAccessToken();
            handleFacebookAccessToken(accessToken);
    
            GraphRequest request = GraphRequest.newMeRequest(accessToken, new GraphRequest.GraphJSONObjectCallback() {
                @Override
                public void onCompleted(JSONObject jsonObject, GraphResponse graphResponse) {
                    if(jsonObject != null){
                        Profile profile = Profile.getCurrentProfile();
                        String userEmail = jsonObject.optString("email"); // Facebook userEmail
    
                    } 
                }
            });
            Bundle bundle = new Bundle();
            bundle.putString("fields", "email");
            request.setParameters(bundle);
            request.executeAsync();
        }
    
        @Override
        public void onCancel() {}
    
        @Override
        public void onError(FacebookException exception) {}
    });
    

    And this the way in which you can check wherever your user loged-in with Google or Facebook.

    if (firebaseUser != null) {
        for (UserInfo userInfo : firebaseUser.getProviderData()) {
            if (userInfo.getProviderId().equals("facebook.com")) {
                Toast.makeText(MainActivity.this, "User is signed in with Facebook", Toast.LENGTH_SHORT).show();
            }
    
            if (userInfo.getProviderId().equals("google.com")) {
                createShoppingList(userModel, listName);
                Toast.makeText(MainActivity.this, "You are signed in Google!", Toast.LENGTH_SHORT).show();
            }
        }
    }