firebase / firebase-js-sdk

Firebase Javascript SDK
https://firebase.google.com/docs/web/setup
Other
4.82k stars 884 forks source link

`verifyPhoneNumber` errors with `auth/invalid-app-credential` only on localhost #8387

Open MaciejCaputa opened 1 month ago

MaciejCaputa commented 1 month ago

Operating System

macOS Sonoma 14.2.1

Browser Version

Chrome 126.0.6478.183

Firebase SDK Version

10.12.4

Firebase SDK Product:

AppCheck, Auth

Describe your project's tooling

Next.js using firebase app check with reCAPTCHA Enterprise with configured debug app check token

Describe the problem

On localhost verifyPhoneNumber calls following endpoint

https://identitytoolkit.googleapis.com/v2/accounts/mfaSignIn:start?key=<api-key>

which returns

{
  "error": {
    "code": 400,
    "message": "INVALID_APP_CREDENTIAL",
    "status": "INVALID_ARGUMENT"
  }
}

Steps and code to reproduce issue

  1. Call verifyPhoneNumber in multifactor authentication flow on localhost

Important facts

google-oss-bot commented 1 month ago

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

odina101 commented 1 month ago

firebase has issue on its servers

shahsagarm commented 1 month ago

I'm also facing the same exact issue. It suddenly stopped working locally but on deployed version (vercel) it works fine with same firebase config.

MaciejCaputa commented 1 month ago

firebase has issue on its servers

Do they know they have an issue? Are they working on the fix? Is there a ticket we can track?

ricardodebeijer commented 1 month ago

We are also having this issue, with a Ionic Cordova app, since past friday. We have a P1 ticket opened at GCP support currently.

Sam-Persoon commented 1 month ago

We also have a ticket opened at GCP. For those that want a temporary workaround, you can serve on 127.0.0.1 instead of localhost and add 127.0.0.1 in Firebase console -> authentication -> settings -> authorised domains.

MaciejCaputa commented 1 month ago

We also have a ticket opened at GCP. For those that want a temporary workaround, you can serve on 127.0.0.1 instead of localhost and add 127.0.0.1 in Firebase console -> authentication -> settings -> authorised domains.

I tried 127.0.0.1 and added it as an authorized domain, but it didn't work for me. Perhaps it is because we use reCaptcha Enterprise where we don't have whitelisted 127.0.0.1

LizDodion commented 1 month ago

Also seeing this

I added 127.0.0.1 as an authorised domain and switched our app to do that and it worked fine

Would be great if firebase can fix asap as we have a lot of other apps that need to be reconfigured and don't want to have to add everywhere

jbalidiong commented 1 month ago

Hi @MaciejCaputa, thanks for reaching out to us. I was able to replicate the behavior. Let me check what we can do for this issue with our Auth team or bring someone here that can provide more context about it. I’ll update this thread if I have any information to share.

deepakrh185 commented 1 month ago

I'm encountering the same issue in my React project. It seems to only occur in the web app, while it works fine on mobile.

saharvx9 commented 1 month ago

Working only for test numbers, i am getting this error too in flutter with "signInWithPhoneNumber"

Sumit-Mayani commented 1 month ago

I'm encountering the same issue in my React project. It seems to only occur in the web app, while it works fine on mobile.

its working in mobile correctly but issue face only on web

Sumit-Mayani commented 1 month ago

We also have a ticket opened at GCP. For those that want a temporary workaround, you can serve on 127.0.0.1 instead of localhost and add 127.0.0.1 in Firebase console -> authentication -> settings -> authorised domains.

not working

ansh commented 1 month ago

I'm having this issue as well on a NextJS 14 app using app router. Other authentication mechanisms work, like anonymous auth and email auth.

yeonjoonkim commented 1 month ago

Hi I am having same problem with phone authentication on localhost.

I have included localhost and 127.0.0.1 into firebase console and google cloud

  1. Firebase Console => Authentication => Setting => Approved Domain

    • localhost
    • 127.0.0.1
  2. Google Cloud => Project => Credential => OAuth 2.0 Client ID => Authroised Javascript ...

    • http://localhost
    • https://localhost
    • http://127.0.0.1
    • https://127.0.0.1
    • https://localhost:8100
    • https://localhost:8101
    • https://localhost:5000

Error Code

https://identitytoolkit.googleapis.com/v1/accounts:sendVerificationCode?key=${key} Request method: Post Access-Control-Allow-Origin: http:localhost:8100

Response: {
  "error": {
    "code": 400,
    "message": "INVALID_APP_CREDENTIAL",
    "errors": [
      {
        "message": "INVALID_APP_CREDENTIAL",
        "domain": "global",
        "reason": "invalid"
      }
    ]
  }
}

Environment

package

    "@angular/animations": "^18.1.1",
    "@angular/cdk": "^18.1.1",
    "@angular/common": "^18.1.1",
    "@angular/core": "^18.1.1",
    "@angular/fire": "^18.0.1",
    "@angular/forms": "^18.1.1",
    "@angular/localize": "^18.1.1",
    "@angular/platform-browser": "^18.1.1",
    "@angular/platform-browser-dynamic": "^18.1.1",
    "@angular/router": "^18.1.1",
    "@angular/service-worker": "^18.1.1",
    "firebase": "10.12.4",

Phone Authentication Code

  public async sendOTP(ph: string): Promise<void> {
    try {
      this.registerRecaptchaDiv();
      const verificationId = await this.getVerificationId(ph);
      this.phoneCodeSentEvent$.next(verificationId);
    } catch (error) {
      this.errorMsg$.next(getErrorMsg(error));
    }
  }

    public async confirmOTP(verificationId: string, verificationCode: string): Promise<void> {
    try {
      const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
      const userCredential = await signInWithCredential(this.auth, authCredential);

      this.signInResult$.next(userCredential?.user ?? null);
    } catch (error) {
      this.errorMsg$.next(getErrorMsg(error));
    }
  }

    private registerRecaptchaDiv() {
    const recaptchContainer = document.getElementById('recaptcha-container');

    if (recaptchContainer) {
      const parent = recaptchContainer.parentNode;
      parent?.removeChild(recaptchContainer);

      const newRecaptchContainer = document.createElement('div');
      newRecaptchContainer.id = 'recaptcha-container';
      parent?.appendChild(newRecaptchContainer);
    }
  }

    private getVerificationId(ph: string) {
    const appVerifier = new RecaptchaVerifier(this.auth, 'recaptcha-container', {
      size: 'invisible',
      callback: (response: any) => {
        console.log('Recaptcha verified');
      },
    });

    const provider = new PhoneAuthProvider(this.auth);
    const verificationId = provider.verifyPhoneNumber(ph, appVerifier);
    appVerifier.clear();
    return verificationId;
  }
diffractometer commented 1 month ago

+1 seeing this issue a lot lately

DellaBitta commented 1 month ago

Hi all,

This error is due a change in Auth Service policy which no longer supports localhost for verifyPhoneNumber invocations. The new guidance is part of our documentation here.

The Auth team has suggested the use of fictional phone numbers for testing purposes.

I'm going to remove the bug label from this issue but I'll leave it open for any questions that may arise. Thanks.

ansh commented 1 month ago

Can we get some context around why localhost is no longer allowed? @DellaBitta

yeonjoonkim commented 1 month ago

@DellaBitta

Hi If we create a fictional phone auth, do they have prefixed id?

Or

Is there have any firebase sdk that allow us to create fictional phone auth by firebase function so that allow us to allocate the resources to fictional phone auth.

diffractometer commented 1 month ago

echoing @ansh kinda bogus but thanks for the update

willemjanvankranenburg commented 1 month ago

@DellaBitta Can you elaborate why this is changed? A lot (if not all) of hybrid apps use localhost as the url to show the pages in the android/iOS web view, even when it's a signed production build. This is not something that a normal developer can change.

Also when having a user base that can use their own phone number to login simply saying "use of fictional phone numbers for testing purposes" is not acceptable.

It's also not acceptable that this is changed by the firebase auth team without notifying users. We have hybrid apps in production for hundreds of business users. They suddenly cannot login anymore and we need to hotfix a workaround for them.

Sam-Persoon commented 1 month ago

Agreeing with @willemjanvankranenburg, this indeed requires a sudden code change in a lot of moving parts in our ecosystem. Because no one was notified, there were also a lot of resources spend into researching the issue in the first place.

The new guidance is part of our documentation here.

@DellaBitta it is quite ironic/confusing as localhost was (is?) added as an authorised domain by default.

MJSPollard commented 1 month ago

I am having this issue. Not even using the firebase SDK though. I am directly calling the identity toolkit google API's from my Node backend and locally it is failing every time now even though I have not changed anything in my app in weeks.

edit: ah I now see the comment that Google changed their policy. Crazy they can just roll this out without warning. The error message also does not help at all in discovering this.

Hilton-Borah commented 1 month ago

Same for me also. I am facing this issue from last two days. Finally I get some response.

Can anyone explain about this, I am new in firebase

Cross origin redirect sign-in on Google Chrome M115+ is no longer supported, and will stop working on June 24, 2024. Migrate to an alternative solution before June 24, 2024 End-users can continue to sign in to your app until June 24, 2024 This is already required on Firefox 109+ and Safari 16.1+

Will it affect on auth services ?

pnede3 commented 1 month ago

Tonight I wanted to update my nextjs app with 2fa by SMS, and after a few hours I found this. Can you please update the guide on 2fa by SMS with some information that localhost is not working?

kamasuPaul commented 1 month ago

Same issue here. Using Quasar framework with capacitor. It works on web(hosted version), but it doesn't work in the mobile app (that uses localhost)

KhoubraneX commented 1 month ago

I had the same issue while developing my app, and I believe the problem was related to using localhost. Here are the steps I followed to resolve it:

I used Visual Studio Code's port forwarding feature, which can be found in the Remote Explorer panel, to change from localhost:port to a URL, like https://x1lpjwcv-port.euw.devtunnels........

I added the domain provided by Visual Studio Code to Firebase by navigating to Firebase Console, Authentication > Settings > Authorized Domains and entering the domain there.

After doing this, everything worked fine.

touy commented 1 month ago

I have the same issues with localhost and ionic capacitor project, it was working before , now it has the issue : FirebaseError: Firebase: Error (auth/invalid-app-credential). with testing phonenumber just work fine , not working with new phonenumber .

jhonny-ventiades commented 1 month ago

Any solution with this issue? I have an application that works with Ionic and Capacitor, we have already tried all the solutions proposed in the thread, but the problem persists. I currently have that authentication method not working and many of my users cannot login in the app.

NhienLam commented 1 month ago

Hi everyone,

We implemented a change to disallow Phone Auth from localhost to address a potential vulnerability that could have led to exploitation. While we recognize this change may have unintended consequences from some developers, we cannot rollback the fix due to the security risk it poses.

Impacted project owners will receive communication on next steps soon. We apologize for any inconvenience this has caused.

aem commented 1 month ago

@NhienLam how are users of the SDK expected to test implementations if not on localhost? Am I expected to write an authentication path and then ship it to prod without testing it? This is occurring even when using the configured test phone numbers.

NhienLam commented 1 month ago

Hi @aem, for local development testing, you should be able to use configured fictional phone numbers or Auth Emulator. Additionally, you can use 127.0.0.1 to test as mentioned above.

This is occurring even when using the configured test phone numbers.

You won't see auth/invalid-app-credential error when using the configured fictional phone number.

aem commented 1 month ago

I've been using fictional phone numbers and they do not work, I get the same error.

Observe, the phone number I'm sending with my verification request:

image

Properly configured as a test phone number for SMS:

image

But still produces auth/invalid-app-credential when I call verifyPhoneNumber

NhienLam commented 1 month ago

@aem that's odd. We verified that using fictional phone numbers worked.

  1. Could you try sending the request with "+15555555555" instead of "+1 555-555-5555"?
  2. Could you make sure you configured the fictional phone number in the correct project that you were testing?
touy commented 1 month ago

Hi everyone,

We implemented a change to disallow Phone Auth from localhost to address a potential vulnerability that could have led to exploitation. While we recognize this change may have unintended consequences from some developers, we cannot rollback the fix due to the security risk it poses.

Impacted project owners will receive communication on next steps soon. We apologize for any inconvenience this has caused.

oh, this is a bad dream all ionic project use a webview with localhost , so all ionic capacitor would be a trash , I have checked my website could work well with a proper domain , but it could not work for ionic capacitor project , that is a bad dream

rscotten commented 1 month ago

@NhienLam Why is it that 127.0.01 is allowed but localhost isn't? Wouldn't they have the same security vulnerabilities?

Also, whoever rolled out this update could have saved thousands of developers many hours just by having a more informative error message like localhost is no longer allowed for Multi Factor phone authentication. Use 127.0.0.1 instead. Read more (link).

If Google/Firebase actually cares about their users, they should really consider the economic cost of bad error messages like this before rolling them out unannounced.

kondricz commented 1 month ago

Hello,

Anyone else having this issue coming up in a hosted environment?

I have not found a pattern yet, but the error is showing up in our systems even when deployed. I have not found a reproducable pattern yet, but some of our developers are facing this issue regularly, especially in in-app browsers (like browser from instagram, browser from telegram).

We use nextJS.

MaciejCaputa commented 1 month ago

Hello,

Anyone else having this issue coming up in a hosted environment?

I have not found a pattern yet, but the error is showing up in our systems even when deployed. I have not found a reproducable pattern yet, but some of our developers are facing this issue regularly, especially in in-app browsers (like browser from instagram, browser from telegram).

We use nextJS.

We also use NextJS and experience that on products sometimes (15% of times) SMS codes are not delivered. We have not yet verified if it is because of this issue, or another issue, but I can't imagine mobile carriers loosing around 15% of SMS.

Can anybody advise how we can report it?

touy commented 1 month ago

@NhienLam Why is it that 127.0.01 is allowed but localhost isn't? Wouldn't they have the same security vulnerabilities?

Also, whoever rolled out this update could have saved thousands of developers many hours just by having a more informative error message like localhost is no longer allowed for Multi Factor phone authentication. Use 127.0.0.1 instead. Read more (link).

If Google/Firebase actually cares about their users, they should really consider the economic cost of bad error messages like this before rolling them out unannounced.

ionic capacitor or any hybrid app is dead now , customers complained and just wait for this issue to be fixed soon

trauma-and-drama commented 1 month ago

It is beyond my belief that Google just changes these things unilaterally without proper communication / documentation. Aside of the 'localhost' issue we are experiencing from a good number of users with that same error on production. Suddently without touching the code.

The only solution for us now is to throw out this gcp auth garbage and do our own flows. Google developers need to understand that such breaking changes or whatever this is are hurting mission critical projects. And there is no room for slack for us.

gvillaume commented 1 month ago

For anyone using ionic capacitor, the localhost issue can be fixed in production by updating the server hostname in your capacitor.config.ts file.

Ex.

const config: CapacitorConfig = {
...
  server: {
    hostname: 'my-app.com',
    androidScheme: 'https',
  }
};

Here's the documentation: https://capacitorjs.com/docs/guides/autofill-credentials#set-capacitor-server-hostname

diffractometer commented 1 month ago

+1 seeing this in production a fair amount auth/invalid-app-credential cc @kondricz

kondricz commented 1 month ago

Hey everyone,

Did Google rolled back this update? I just tested it now (with non-testing real number) on localhost, and it is working again finally.

LizDodion commented 1 month ago

It started working back again for me today after not working for a few weeks. hopefully it is now rolled back

trauma-and-drama commented 1 month ago

It started working back again for me today after not working for a few weeks. hopefully it is now rolled back

I can't confirm this. After performing the recaptcha, the error is still appearing for localhost and unclear if it still appears in production. Waiting on client feedback.

ERROR 1: identitytoolkit.googleapis.com/v1/accounts:sendVerificationCode?key=:1 httperror 400 Failed to load resource: the requested URL /v1/accounts:sendVerificationCode?key= was not found on this server. ERROR 2: recaptcha__en.js:249 Uncaught TypeError: Cannot read properties of null (reading 'style')

firebase_core: ^2.25.4 firebase_auth: ^4.17.4

doesn't work with firebase_core: ^3.3.0 firebase_auth: ^5.1.4 either

kondricz commented 1 month ago

I think they are working on it right now. Can someone confirm this from google team?

I had 5 sign ups and it was also working from localhost, but now the error is appearing again. This is VERY BAD. Why can't we just roll it back and release it only when its properly tested and won't break all of our stuff ?

mohsenkhkh commented 1 month ago

We also have a ticket opened at GCP. For those that want a temporary workaround, you can serve on 127.0.0.1 instead of localhost and add 127.0.0.1 in Firebase console -> authentication -> settings -> authorised domains.

I tried 127.0.0.1 and added it as an authorized domain, but it didn't work for me. Perhaps it is because we use reCaptcha Enterprise where we don't have whitelisted 127.0.0.1

did you place 127.0.0.1 instead of localhost in your browser too? that was for me 127.0.0.1:3000 instead of localhost:3000

kondricz commented 4 weeks ago

Any updates here? Our team is still suffering from this.

We are considering just to build this thing on our own or use another provider.

trauma-and-drama commented 4 weeks ago

There seems to be an issue not only with localhost, but potentially proxy or NAT-based networks (can't tell).

We pulled the plug and deployed a custom Phone-Auth via Twillio, Firebase https-Functions, and customTokens. This whole handshake with recaptcha is just too buggy and blackboxy for us, the settings page for recaptcha does not seem to be well integrated. And the support here, is mindboggingly absent on a critical issue like this (3 weeks!!)

My advice to the Google Firebase/GCP team: If you want small businesses to use your services, take more care on breaking changes. The world is more complex beyond your Google cubicle (this is me being nice and mindful).

kondricz commented 3 weeks ago

It is funny for me.

It feels like the team is constantly working on the issue, but they sort of pushing on prod and let us end users test it 😭

Sometimes it works flawlessly for hours or even half a day (I guess this is the time when they restore the older version of the API), then it randomly starts failing for few hours.

Yesterday we had around 100 phone registration and 5 of them failed with this. Is there anyone here who has not migrated to their own solution yet and experiencing the same?