Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SmsRetrieverHelper] SMS verification code request failed: unknown status code: 17499 INVALID_PROJECT_ID:Project ID does not match MFA pending credential #6348

Open
0xPr0xy opened this issue Oct 4, 2024 · 8 comments

Comments

@0xPr0xy
Copy link

0xPr0xy commented Oct 4, 2024

[READ] Step 1: Are you in the right place?

The code isn't in this repository but it is about com.google.firebase:firebase-auth

[REQUIRED] Step 2: Describe your environment

  • Android Studio version: Android Studio Koala | 2024.1.1 Patch 1 Build #AI-241.18034.62.2411.12071903, built on July 10, 2024
  • Firebase Component: Firebase Auth
  • Component version: com.google.firebase:firebase-auth

[REQUIRED] Step 3: Describe the problem

Context
Project is a Flutter app, using Firebase Auth 5.3.1
We are using Firebase Auth with GCP Identity Platform, since we want multi-tenant feature, and Phone 2FA.

Problem
Registering a user, and adding the Phone 2FA to the account using Firebase Auth SDK does work on both Android and iOS.
Logging in a user with 2FA enabled using the Firebase Auth SDK does not work on Android, and does work on iOS.

What works

  • Creating an account using email + password
  • Entering phone number and receiving a verification SMS
  • Entering the verification code and completing adding the phone number as 2FA
  • Result: account added to the specified tenant, with 2FA type phone setup and verified.

What doesn't work

  • When logging out, and trying to login again with email + password
  • Handling the FirebaseAuthMultiFactorException exception as per the documentation
  • Then calling verifyPhoneNumber with the resolver session and first hint
  • We don't get the verification SMS and an error is printed:
  • [SmsRetrieverHelper] SMS verification code request failed: unknown status code: 17499 INVALID_PROJECT_ID:Project ID does not match MFA pending credential

Related (but the issue looks to be Android SDK related and not Flutter related): firebase/flutterfire#9550

Steps to reproduce:

  1. In Google Identity Platform create a user with Email / Password provider
  2. Make the user Multi-factor enrolled with type Phone
  3. Using Firebase Auth SDK (setting tenantId to the tenant where the account exists)
  4. try to sign in with the user

Relevant Code:

👉Code can be shared privately.
👉We can also add you to the test app in Play Store.

Signing in with 2FA handling (codeSent is never called and gives error)

❌Error: [SmsRetrieverHelper] SMS verification code request failed: unknown status code: 17499 INVALID_PROJECT_ID:Project ID does not match MFA pending credential

  Future<bool> login(String email, String password) async {
    try {
      final credential =
          EmailAuthProvider.credential(email: email, password: password);
      await _firebaseAuth.signInWithCredential(credential);
      return true;
    } on FirebaseAuthMultiFactorException catch (e) {
      final firstHint = e.resolver.hints.first;
      if (firstHint is! PhoneMultiFactorInfo) {
        return false;
      }

      // Completer to wait for the phone verification to finish
      final Completer<bool> completer = Completer();
      // Completer to wait for the SMS code to return
      final Completer<String?> smsCompleter = Completer<String?>();

      await _firebaseAuth.verifyPhoneNumber(
        multiFactorSession: e.resolver.session,
        multiFactorInfo: firstHint,
        verificationCompleted: (_) => completer.complete(true),
        verificationFailed: (FirebaseAuthException error) =>
            completer.complete(false),
        codeSent: (String verificationId, int? resendToken) async {
          // Irrelevant code..
          // Wait for SMS code
          final smsCode = await smsCompleter.future;
          if (smsCode != null) {
            final phoneCredential = PhoneAuthProvider.credential(
                verificationId: verificationId, smsCode: smsCode);
            try {
              await e.resolver.resolveSignIn(
                  PhoneMultiFactorGenerator.getAssertion(phoneCredential));
              completer.complete(true);
            } on FirebaseAuthException catch (e) {
              debugPrint("Error resolving sign-in: ${e.message}");
              completer.complete(false);
            }
          } else {
            completer.complete(false);
          }
        },
        codeAutoRetrievalTimeout: (_) => completer.complete(false),
      );

      return await completer.future;
    } catch (e) {
      debugPrint("Login error: $e");
      return false;
    }
  }

Registering 2FA (works)

  Future<void> setupTwoFactorAuthentication(String phoneNumber,
      {required Function(String verificationId, int? resendToken) onCodeSent,
      required Function(FirebaseAuthException error)
          onVerificationFailed}) async {
    try {
      final multiFactorSession =
          await _firebaseAuth.currentUser?.multiFactor.getSession();
      await _firebaseAuth.verifyPhoneNumber(
        multiFactorSession: multiFactorSession,
        phoneNumber: phoneNumber,
        verificationCompleted: (_) {},
        verificationFailed: (FirebaseAuthException e) =>
            onVerificationFailed(e),
        codeSent: (String verificationId, int? resendToken) =>
            onCodeSent(verificationId, resendToken),
        codeAutoRetrievalTimeout: (String verificationId) {
          // Handle the auto-retrieval timeout if necessary
        },
      );
    } on FirebaseAuthException catch (e) {
      // TODO: Error snackbar.
      debugPrint("setupTwoFactorAuthentication FirebaseAuthException: $e");
      onVerificationFailed(e);
    } catch (e) {
      // TODO: Error snackbar.
      debugPrint("setupTwoFactorAuthentication error: $e");
    }
  }

  Future<void> validateTwoFactorAuthentication(
      String phoneNumber, String smsCode, String verificationCode) async {
    final credential = PhoneAuthProvider.credential(
      smsCode: smsCode,
      verificationId: verificationCode,
    );
    return await _firebaseAuth.currentUser?.multiFactor.enroll(
        PhoneMultiFactorGenerator.getAssertion(credential),
        displayName: phoneNumber);
  }

Debug logs + screenshot of the created account in GCP:

bug.zip

@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@0xPr0xy
Copy link
Author

0xPr0xy commented Oct 7, 2024

Hello, just checking back to see if there's any update on this.
Since this is critical for our project, we're trying to determine if we can wait for a possible resolution or if we need to look to another solution for this.
In order for us to decide the way forward, Could you share what would be a realistic timeline for this ticket to a) being assigned to someone, and then b) to possibly a fix being released?

@lehcar09
Copy link
Contributor

lehcar09 commented Oct 7, 2024

Hi @0xPr0xy, thank you for reaching out. I tried reproducing the issue, however, I'm encountering a different error. Can you share an MCVE to help us investigate the issue? You can try our quickstart app and work from there to reproduce the issue. Thanks!

@0xPr0xy
Copy link
Author

0xPr0xy commented Oct 8, 2024

@lehcar09

Hi @0xPr0xy, thank you for reaching out. I tried reproducing the issue, however, I'm encountering a different error. Can you share an MCVE to help us investigate the issue? You can try our quickstart app and work from there to reproduce the issue. Thanks!

I have created a private repository and invited you as contributor: https://github.com/0xPr0xy/firebase-auth-MCVP/
See the readme on steps to reproduce the error.

Kind regards

@lehcar09
Copy link
Contributor

lehcar09 commented Oct 9, 2024

Thank you for additional information @0xPr0xy. After running your MCVE, I still wasn’t able to reproduce the issue.
Based on the code change within your MCVE, you are setting the tenant in your app. Just to note, according to our documentation:

Note: Using multi-factor authentication with multiple tenants is not supported on Android.

This could be the cause of the issue that you’re experiencing. Could you try removing the line where you set the tenant ID?

multiFactorResolver.firebaseAuth.setTenantId("tenant ID")

In addition to that, Phone Authentication/ SMS multi-factor Auth uses a lot of signals to prevent fraud. This means:

  • It can't work on an emulator. You'll need to test on a real device (and not rooted).
  • A version of the application which was not installed directly from the Play Store.

To add, the error you’re encountering could be due to misconfiguration in the Android app or the Firebase project settings. It's possible that the Android app is configured to use a different Firebase project ID than the one where the user's phone number is registered for 2FA.

I suggest verifying the Firebase project configuration in the Android app. Ensure that the correct google-services.json file is included in the Android project and that the package names match across the Firebase console, Google Cloud Platform project, and the Android app. Double-check that the SHA-1 certificate fingerprint of the Android app is correctly registered in the Firebase project settings.

That said, I’ll close this issue for now. To get better help, try reaching out to the Firebase Support channel. We'd need access to your project settings (including projectID, SHA-1 etc) to troubleshoot this type of issue. Please do keep in mind that our SDK support team does not have access to the backend or your project details.

@0xPr0xy
Copy link
Author

0xPr0xy commented Oct 9, 2024

@lehcar09

After running your MCVE, I still wasn’t able to reproduce the issue.

That's very strange we can reproduce this issue consistently both in an app installed from the Play Store on a real device (internal testing). but also on the MCVE running in an Android simulator. (SDK SHA added to firebase).

Note: Using multi-factor authentication with multiple tenants is not supported on Android.

I've indeed read that, however it's unclear when the documentation was last updated as support for setting tenants was added pretty recently, and the iOS documentation says the same thing, yet it MFA with multi tenancy fully works on iOS.

To add, the error you’re encountering could be due to misconfiguration in the Android app or the Firebase project settings.

We're pretty sure we have resolved all those errors by adding com.google.android.play:integrity and adding the debug token + SDK SHA to firebase.

Additionally, keep in mind that we are able to correctly sign up a user including adding and verifying the second factor on a multi tenant. so when registering the 2FA phone verification SMS is sent correctly for the multi-tenant registered user.
That makes it odd that upon logging in, that same verification SMS is giving this error.
What are your thoughts on that?

@lehcar09
Copy link
Contributor

Thank you for clarifying the details. Let me raise this to our engineering team. I'll get back to you as soon as I hear back from them. Thanks!

@0xPr0xy
Copy link
Author

0xPr0xy commented Oct 15, 2024

@lehcar09 Just checking back here, do you have any idea when we can expect a reply from engineering team?
Also I could help you reproduce the issue if you send me your Android SDK SHA + Debug token (assuming that when you said you couldn't reproduce the issue that was caused by a different error you got?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants