Phone Number Verification

Installation and getting started with Phone Number Verification.

Installation

This module requires that the @react-native-firebase/app module is already setup and installed. To install the "app" module, view the Getting Started documentation.

bash
# Install & setup the app module
yarn add @react-native-firebase/app

# Install the phone-number-verification module
yarn add @react-native-firebase/phone-number-verification

Android only - This module is only available on Android. The Firebase Phone Number Verification SDK does not support iOS or web platforms. Calling any method on a non-Android platform will throw an error.

Platform support and New Architecture

PlatformsAndroid only
New ArchitectureRequired from v26. See Migrating to v26.

What does it do

Firebase Phone Number Verification provides carrier-level phone number verification on Android devices without requiring SMS codes. It verifies the user's phone number directly through the device's SIM card and carrier network, providing a seamless and secure verification experience.

To learn more, visit the Firebase Phone Number Verification documentation.

Key capabilities:

  • Carrier-level verification: Verifies phone numbers directly with the mobile carrier, without SMS.
  • Support detection: Check whether the device and carrier support phone number verification before attempting it. This does not require user consent.
  • Verified phone number: Retrieve the device's verified phone number as a JWT token containing the phone number, timestamps, nonce, and claims. This will present a consent dialog to the user.
  • Digital Credential API: Supports the Android Digital Credential API for custom verification flows.

Region & carrier limitations

Phone Number Verification depends on carrier cooperation. Not all carriers or regions are supported. Before relying on Phone Number Verification, always call getVerificationSupportInfo() to check support. If a SIM slot returns reason: 'INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED', that carrier does not participate in Phone Number Verification and you should fall back to another verification method (e.g. Firebase Auth SMS).

Common reasons verification may be unsupported:

ReasonMeaning
CAPABLEThe SIM's carrier supports Phone Number Verification.
INCAPABLE_DUE_TO_CARRIER_UNSUPPORTEDThe carrier does not participate in Phone Number Verification.
INCAPABLE_DUE_TO_ANDROID_VERSIONThe device's Android version is too old.
INCAPABLE_DUE_TO_SIM_STATENo SIM inserted, or SIM is in an unusable state.
CAPABILITY_STATUS_UNSPECIFIEDThe SDK could not determine the status.

Usage

Check verification support

Before attempting verification, check if the device's SIM card(s) support phone number verification. This call does not require user consent and can be called freely:

js
import { getVerificationSupportInfo } from '@react-native-firebase/phone-number-verification';

const supportInfo = await getVerificationSupportInfo();

for (const info of supportInfo) {
  console.log(`SIM slot ${info.simSlot}:`);
  console.log('  Supported:', info.isSupported);
  console.log('  Carrier ID:', info.carrierId);
  console.log('  Reason:', info.reason);
}

The method returns an array with one entry per SIM slot. Each entry includes:

  • isSupported — whether Phone Number Verification is available for this SIM.
  • simSlot — the SIM slot index (0-based).
  • carrierId — the carrier identifier string.
  • reason — a VerificationSupportStatus string explaining why the SIM is or isn't supported.

Query a specific SIM slot

On dual-SIM devices, you can query a specific SIM slot by passing the slot index:

js
import { getVerificationSupportInfo } from '@react-native-firebase/phone-number-verification';

const supportInfo = await getVerificationSupportInfo(0); // SIM slot 0

Fallback when unsupported

If Phone Number Verification is not supported, fall back to an alternative verification method:

js
import { Platform } from 'react-native';
import {
  getVerificationSupportInfo,
  getVerifiedPhoneNumber,
} from '@react-native-firebase/phone-number-verification';

async function verifyPhoneNumber() {
  if (Platform.OS !== 'android') {
    // Use SMS-based verification on non-Android platforms
    return verifySms();
  }

  const supportInfo = await getVerificationSupportInfo();
  const supported = supportInfo.some(info => info.isSupported);

  if (supported) {
    try {
      return await getVerifiedPhoneNumber();
    } catch (error) {
      // Fall back to SMS on failure
      return verifySms();
    }
  }

  // Carrier or device doesn't support Phone Number Verification
  return verifySms();
}

Verify a phone number

To initiate the full verification flow, call getVerifiedPhoneNumber(). This will present a consent dialog to the user asking permission to share their phone number. Your app should prepare the user for this consent screen before calling the method — for example, by explaining why their phone number is needed.

For guidance on handling user consent, see the Firebase Phone Number Verification getting started guide.

js
import { getVerifiedPhoneNumber } from '@react-native-firebase/phone-number-verification';

try {
  const result = await getVerifiedPhoneNumber();
  console.log('Phone number:', result.phoneNumber);
  console.log('Token:', result.token);
  console.log('Expires at:', new Date(result.expirationTimestamp * 1000));
  console.log('Issued at:', new Date(result.issuedAtTimestamp * 1000));
  console.log('Nonce:', result.nonce);
  console.log('Claims:', result.claims);
} catch (error) {
  console.error('Verification failed:', error.code, error.message);
}

The returned result includes:

  • phoneNumber — the verified phone number in E.164 format.
  • token — the raw JWT token string for server-side validation.
  • expirationTimestamp — token expiration as Unix epoch seconds.
  • issuedAtTimestamp — token issued-at time as Unix epoch seconds.
  • nonce — the nonce from the JWT payload, or null.
  • claims — all JWT claims as a key-value map, or null.

Custom verification with Digital Credentials

For advanced use cases, you can use the Digital Credential API flow:

js
import {
  getDigitalCredentialPayload,
  exchangeCredentialResponseForPhoneNumber,
} from '@react-native-firebase/phone-number-verification';

// Step 1: Get the credential payload
const payload = await getDigitalCredentialPayload('your-unique-nonce');

// Step 2: Use the payload with Android Credential Manager
// ... (pass payload to CredentialManager API)

// Step 3: Exchange the response for a verified phone number
const result = await exchangeCredentialResponseForPhoneNumber(credentialResponse);
console.log('Phone number:', result.phoneNumber);
console.log('Expires at:', new Date(result.expirationTimestamp * 1000));

Error handling

All methods reject with structured error codes from the Firebase Phone Number Verification SDK. The error.code property contains one of these values:

Error CodeMeaning
pnv/carrier-not-supportedThe SIM's carrier does not support Phone Number Verification.
pnv/invalid-digital-credential-responseThe Digital Credential API response was invalid.
pnv/integrity-check-failedDevice integrity check failed.
pnv/preflight-check-failedServer-side preflight check failed.
pnv/unsupported-operationThe API call is not supported with the given parameters.
pnv/credential-manager-errorAndroid Credential Manager failed unexpectedly.
pnv/invalid-test-number-idTest number IDs are empty, expired, or duplicated.
pnv/test-session-already-enabledenableTestSession was called more than once.
pnv/activity-context-requiredAn Activity context is required (app may be in the background).
ts
import {
  getVerifiedPhoneNumber,
  PnvErrorCode,
  type PnvError,
} from '@react-native-firebase/phone-number-verification';

try {
  const result = await getVerifiedPhoneNumber();
} catch (error) {
  const pnvError = error as PnvError;

  switch (pnvError.code) {
    case PnvErrorCode.CARRIER_NOT_SUPPORTED:
      // Fall back to SMS verification
      break;
    case PnvErrorCode.ACTIVITY_CONTEXT_REQUIRED:
      // Retry when app is in foreground
      break;
    default:
      console.error('Phone Number Verification error:', pnvError.code, pnvError.message);
  }
}

Testing

To test without a real SIM card and carrier, use Firebase's test mode. This requires setup in the Firebase Console:

  1. Generate a test token: In the Firebase Console, navigate to Phone Number Verification and generate a test token. Test tokens have a 7-day Time-To-Live.
  2. Identity and Access Management permissions: Ensure the service account has the required firebasepnv.testSessions.create permission.
  3. Google system services beta: On the test device, enroll the Google system services app into the beta channel via Google Play.
  4. Call enableTestSession once: Pass the token before any verification calls. This must be called only once per app instance — calling it again will reject with pnv/test-session-already-enabled.
js
import {
  enableTestSession,
  getVerifiedPhoneNumber,
} from '@react-native-firebase/phone-number-verification';

// Call once at app startup for testing
await enableTestSession('your-test-token-from-firebase-console');

// Now verification calls return test data
// Phone numbers in test mode follow the format: valid country code + all zeros
const result = await getVerifiedPhoneNumber();
console.log('Test phone number:', result.phoneNumber);

Platform handling

This module is Android-only. On non-Android platforms, all methods throw an error with the message "Firebase Phone Number Verification is only supported on Android." You can guard against this using Platform.OS:

js
import { Platform } from 'react-native';
import { getVerificationSupportInfo } from '@react-native-firebase/phone-number-verification';

if (Platform.OS === 'android') {
  const supportInfo = await getVerificationSupportInfo();
  // ...
}