Skip to content

[firebase_auth/web] Persistent auth/error-code:-39 (503 Service Unavailable) with Phone Auth on Blaze Plan (Real Numbers Only) #8955

Closed
@vlantiguam

Description

@vlantiguam

Operating System

Windows 10

Environment (if applicable)

Chrome Versión 135.0.7049.96 (Build oficial) (64 bits), node -v v22.14.0, Nuxt 3

Firebase SDK Version

firebase": "^10.13.1",

Firebase SDK Product(s)

Auth

Project Tooling

Nuxt.js 3 app using Vite, deployed on Firebase Hosting.

Detailed Problem Description

Description:

We are encountering a persistent issue with Firebase Phone Authentication (signInWithPhoneNumber) in our Nuxt.js web application hosted on Firebase Hosting (rdmercana.web.app).

Expected behavior:
Successfully send SMS verification codes to real phone numbers using signInWithPhoneNumber.

Actual behavior:
When attempting to send a verification code to any real phone number, the process fails immediately. We observe the following errors:

  1. In the web application UI/console: FirebaseError: Error (auth/error-code:-39)
  2. In the browser's network tab: A POST request to https://identitytoolkit.googleapis.com/v1/accounts:sendVerificationCode?key=... fails with a 503 (Service Unavailable) status code.

Importantly, this issue does not occur when using the test phone numbers configured within the Firebase Authentication settings. Test numbers work correctly.

Our Firebase project is on the Blaze (Pay-as-you-go) plan.

Troubleshooting Steps Taken:

  • Verified that the Identity Platform API is enabled in the linked Google Cloud project.
  • Verified that the web app's domain (rdmercana.web.app) and localhost are included in the Authorized Domains list in Firebase Auth settings.
  • Verified the API Key restrictions in Google Cloud Console:
    • HTTP referrers include rdmercana.web.app/* and relevant localhost entries.
    • API restrictions allow the Identity Platform API (or keys are unrestricted).
  • Verified the Firebase configuration details (apiKey, authDomain, projectId) in our Nuxt.js application are correct.
  • Disabled reCAPTCHA Account Defender in the Google Cloud Console (the issue persisted).
  • Confirmed test phone numbers work correctly.
  • Waited over 24 hours to allow potential temporary anti-abuse blocks or rate limits to expire, but the issue persists for real numbers.

Hypothesis:
Given that test numbers function correctly and we are on the Blaze plan, the issue seems related to Firebase's anti-abuse or security mechanisms specifically affecting SMS delivery to real numbers for our project. It might be a persistent block or limit that hasn't cleared automatically, as suggested in similar issues like firebase/flutterfire#3817.

We require assistance in diagnosing why real numbers are consistently failing with auth/error-code:-39 / 503 despite the correct configuration and Blaze plan status. Is there a way to investigate potential blocks or gain more insight into the specific reason for the failure?


Steps to reproduce:

  1. Set up Firebase Phone Authentication in a web project (using Firebase JS SDK v[ "^10.13.1",]).
  2. Ensure the project is on the Blaze plan, Identity Platform API is enabled, the domain is authorized, and API key restrictions are correctly configured (allow Identity Platform and HTTP referrers). Ensure Account Defender is disabled.
  3. Use a component similar to the one described below to implement the phone sign-in flow using signInWithPhoneNumber and an invisible RecaptchaVerifier.
  4. Deploy the application (e.g., to Firebase Hosting).
  5. Attempt to sign in using a configured test phone number: Enter the test number and trigger the signInWithPhoneNumber function.
    • Expected: The invisible reCAPTCHA should pass, and the function should resolve successfully, proceeding to the code verification step.
    • Actual: This works correctly as expected.
  6. Attempt to sign in using a real phone number (e.g., +1829xxxxxxx): Enter a valid, real phone number and trigger the signInWithPhoneNumber function.
    • Expected: The invisible reCAPTCHA should pass, the SMS code should be sent, and the function should resolve successfully.
    • Actual: The signInWithPhoneNumber function fails almost immediately. The browser console shows FirebaseError: Error (auth/error-code:-39), and the network request to identitytoolkit.googleapis.com/.../accounts:sendVerificationCode shows a 503 Service Unavailable error. This happens consistently for real numbers despite waiting periods.

Relevant Code Snippet (Simplified Logic from our LoginPhone.vue):

```javascript
import { RecaptchaVerifier, signInWithPhoneNumber } from 'firebase/auth';
// ... other imports and setup ...

const auth = getAuth(); // Assuming $auth is initialized getAuth() result
const phoneNumber = ref('+1...'); // User input for real phone number
const recaptchaVerifier = ref(null);
const confirmationResult = ref(null);
const loading = ref(false);
const errorMessage = ref('');

onMounted(() => {
recaptchaVerifier.value = new RecaptchaVerifier(auth, 'recaptcha-container', {
size: 'invisible',
callback: (response) => { console.log('reCAPTCHA verified'); },
'expired-callback': () => { errorMessage.value = 'reCAPTCHA expired'; }
});
recaptchaVerifier.value.render().catch(err => console.error("Recaptcha render error:", err));
});

async function sendVerificationCode() {
loading.value = true;
errorMessage.value = '';
try {
// This is the call that fails for REAL numbers with error -39 / 503
confirmationResult.value = await signInWithPhoneNumber(auth, phoneNumber.value, recaptchaVerifier.value);
// Proceeds to verification step (only reached for test numbers)
console.log('Confirmation result received:', confirmationResult.value);
} catch (error) {
console.error('Error sending verification code:', error); // Logs the auth/error-code:-39
errorMessage.value = `Error: ${error.message}`;
} finally {
loading.value = false;
}
}

// Template would include an input for phoneNumber, a button calling sendVerificationCode,
// and the


```


Relevant Log Output:

```log
Enviando código de verificación SMS...
POST https://identitytoolkit.googleapis.com/v1/accounts:sendVerificationCode?key=[] 503 (Service Unavailable)
Error durante el proceso de envío de código: FirebaseError: Firebase: Error (auth/error-code:-39).
at hd (...)
at wn (...)
at Tw (...)
at async kO (...)
at async jU (...)
at async E (...)
reCAPTCHA v2 (Firebase Auth) reseteado.
```

Steps and code to reproduce issue

Steps to reproduce:

  1. Set up Firebase Phone Authentication in a web project (using Firebase JS SDK v["^10.13.1",]).
  2. Ensure the project is on the Blaze plan, Identity Platform API is enabled, the domain is authorized, and API key restrictions are correctly configured (allow Identity Platform and HTTP referrers). Ensure Account Defender is disabled.
  3. Use a component similar to the one described below to implement the phone sign-in flow using signInWithPhoneNumber and an invisible RecaptchaVerifier.
  4. Deploy the application (e.g., to Firebase Hosting).
  5. Attempt to sign in using a configured test phone number: Enter the test number and trigger the signInWithPhoneNumber function.
    • Expected: The invisible reCAPTCHA should pass, and the function should resolve successfully, proceeding to the code verification step.
    • Actual: This works correctly as expected.
  6. Attempt to sign in using a real phone number (e.g., +1829xxxxxxx): Enter a valid, real phone number and trigger the signInWithPhoneNumber function.
    • Expected: The invisible reCAPTCHA should pass, the SMS code should be sent, and the function should resolve successfully.
    • Actual: The signInWithPhoneNumber function fails almost immediately. The browser console shows FirebaseError: Error (auth/error-code:-39), and the network request to identitytoolkit.googleapis.com/.../accounts:sendVerificationCode shows a 503 Service Unavailable error. This happens consistently for real numbers despite waiting periods.

Relevant Code Snippet (Simplified Logic from our LoginPhone.vue):

```javascript
import { RecaptchaVerifier, signInWithPhoneNumber } from 'firebase/auth';
// ... other imports and setup ...

const auth = getAuth(); // Assuming $auth is initialized getAuth() result
const phoneNumber = ref('+1...'); // User input for real phone number
const recaptchaVerifier = ref(null);
const confirmationResult = ref(null);
const loading = ref(false);
const errorMessage = ref('');

onMounted(() => {
recaptchaVerifier.value = new RecaptchaVerifier(auth, 'recaptcha-container', {
size: 'invisible',
callback: (response) => { console.log('reCAPTCHA verified'); },
'expired-callback': () => { errorMessage.value = 'reCAPTCHA expired'; }
});
recaptchaVerifier.value.render().catch(err => console.error("Recaptcha render error:", err));
});

async function sendVerificationCode() {
loading.value = true;
errorMessage.value = '';
try {
// This is the call that fails for REAL numbers with error -39 / 503
confirmationResult.value = await signInWithPhoneNumber(auth, phoneNumber.value, recaptchaVerifier.value);
// Proceeds to verification step (only reached for test numbers)
console.log('Confirmation result received:', confirmationResult.value);
} catch (error) {
console.error('Error sending verification code:', error); // Logs the auth/error-code:-39
errorMessage.value = `Error: ${error.message}`;
} finally {
loading.value = false;
}
}

// Template would include an input for phoneNumber, a button calling sendVerificationCode,
// and the


```

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions