2

I want to implement signing in to my application using a Google account. I use Firebase to authenticate the user.

I've already read the documentation like million times. I've added SH1 debug key to Firebase project as a fingerprint and I use Web SDK configuration from the Firebase as a web client id: this thing

I've got it set up in strings.xml file

<string name="web_client_id">**HERE**</string>

the rest of my code looks like this:

public class AuthFragment extends Fragment {
    private FragmentAuthBinding binding;
    private SignInClient oneTapClient;
    ActivityResultLauncher<Intent> oneTapLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == Activity.RESULT_OK) {
                Intent data = result.getData();
                try {
                    var credential = oneTapClient.getSignInCredentialFromIntent(data);
                    String idToken = credential.getGoogleIdToken();
                } catch (ApiException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    public AuthFragment() {}

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentAuthBinding.inflate(inflater, container, false);
        return binding.getRoot();
    }

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        
        HandleGoogleLogin();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

    void HandleGoogleLogin()
    {
        oneTapClient = Identity.getSignInClient(requireActivity());
        var signInRequest = BeginSignInRequest.builder()
                .setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                        .setSupported(true)
                        .setServerClientId(getString(R.string.web_client_id))
                        .setFilterByAuthorizedAccounts(false)
                        .build())
                .build();

        var googleLoginButton = binding.googleLoginButton;
        googleLoginButton.setOnClickListener(v -> {
            oneTapClient.beginSignIn(signInRequest)
                    .addOnSuccessListener(requireActivity(), result -> {
                        var intentSenderRequest = new IntentSenderRequest
                                .Builder(result.getPendingIntent().getIntentSender())
                                .build();
                        oneTapLauncher.launch(intentSenderRequest.getFillInIntent());
                    })
                    .addOnFailureListener(requireActivity(), e -> {
                        Log.d("googleLoginButton", "oneTapClient.beginSignIn:onError - " + e.getMessage());
                        // Handle errors or continue presenting the signed-out UI
                    });
        });
    }
}

this is not the only way I've tried to implement it. I've also tried adding sh1 key to https://console.cloud.google.com/ and configuring OAuth 2.0 from the https://console.cloud.google.com/apis/credentials?project=myproject site:

cloud.google

but nothing actually works.

All I always get is Log.d("googleLoginButton", "oneTapClient.beginSignIn:onError - " + e.getMessage()); -> Cannot find a matching credential.

I don't know what I do wrong. Note that I've got setFilterByAuthorizedAccounts set to false.

How can I make it work? What do I do wrong?

I've already read:

Getting "16: Cannot find a matching credential" when doing One Tap sign-in and sign-up on Android

Google One Tap Sign In

Firebase Google auth, signing out and logging in again will log in with the last signed account

When users SignOut of my Firebase app, why doesn't it also SignOut from the auth provider, say Google?

Google Firebase sign out and forget user in Android app

https://medium.com/firebase-developers/how-to-authenticate-to-firebase-using-google-one-tap-in-jetpack-compose-60b30e621d0d

nothing helps.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Are you sure you're authenticated with a Google account on the device where you're launching the app? – Alex Mamo Apr 05 '23 at 06:05
  • I'm not authenticated with a Google account on the device. That's why `setFilterByAuthorizedAccounts` is set to `false`, so I could choose an account I want to log in with. – Edziu Kowalski Apr 05 '23 at 11:29
  • 2
    To choose an account, you have to be authenticated with the account first on the device. Have you even tried it? When you're using `.setFilterByAuthorizedAccounts(false)` it means that you want to show all accounts on the device. If you aren't authenticated, then there is nothing to show. – Alex Mamo Apr 05 '23 at 12:03
  • Oh, alright, so I have to have every google account authenticated on the device? Because, now, that I've authenticated my main google account on the device the authentication inside my app works, but it only shows the main account. I've used other applications and there's almost always an option to authenticate with a new account without adding it to the device. – Edziu Kowalski Apr 05 '23 at 12:30
  • Aside from my answer, since you're using Java, I think that this [resource](https://medium.com/firebase-tips-tricks/how-to-create-a-clean-firebase-authentication-using-mvvm-37f9b8eb7336) will help. Here is the corresponding [repo](https://github.com/alexmamo/FirebaseAuthentication). – Alex Mamo Apr 05 '23 at 13:13
  • 1
    I've already read it. It's a nice resource, I need to read more about the differences between the one tap auth and the "old" way. But now, I have to find out why registerForActivityResult gives Activity.RESULT_CANCEL instead of RESULT_OK... eh.. why it cannot just work hahaha. Thanks for help, though – Edziu Kowalski Apr 05 '23 at 13:31

1 Answers1

3

To be able to choose an account when you authenticate with Google in your app, you have to be authenticated first with that account on the device where you're launching the app.

If you're using in your code .setFilterByAuthorizedAccounts(false) it means that you want to show all accounts on the device. If you are not authenticated with any account, then there is nothing to show but an Exception.

If you want to be able to choose between multiple accounts, then you have to sign in with each account on the device.

I've used other applications and there's almost always an option to authenticate with a new account without adding it to the device.

All devices with Android have associated at least a Google account. So in order to be able to sign in with Google inside your app, you have to be authenticated on your device first or asked to sign in with a Google account.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193