firebase_phone_number_verification
A Flutter plugin for Firebase Phone Number Verification (Firebase PNV).
Firebase PNV is a faster and more secure method for verifying phone numbers. Instead of sending an SMS OTP, it obtains the phone number assigned to the SIM in the device directly from the carrier with a single tap. This:
- reduces friction for the user (no code to receive and type),
- improves reliability (no dependency on SMS delivery),
- eliminates SMS phishing / OTP-interception attack vectors.
Platform support: Firebase PNV is currently available on Android only. On other platforms,
isSupported()returnsfalseso you can fall back to your existing verification method (for example SMS OTP).
Setup
1. Configure your Firebase project
- Add Firebase to your Android app if you haven't already
(guide), including the
google-services.jsonfile and thecom.google.gms.google-servicesGradle plugin. - In the Firebase console, complete the Phone Number Verification onboarding steps (under Security > Phone Verification).
2. Add the plugin
flutter pub add firebase_phone_number_verification
The plugin depends on the native com.google.firebase:firebase-pnv library;
no extra Gradle configuration is needed.
Usage
import 'package:firebase_phone_number_verification/firebase_phone_number_verification.dart';
final fpnv = FirebasePhoneNumberVerification.instance;
Test mode (recommended while developing)
You can try the full flow without a billing account or a real SIM:
- In the Firebase console, go to Security > Phone Verification > Testing and click Generate token.
- Enable a test session with the generated test number ID (valid for 7 days):
await fpnv.enableTestSession('YOUR_TEST_NUMBER_ID');
To use test mode, the device must be enrolled in the Google system services public beta program. Test tokens work on both physical devices and emulators.
Check for support
On app launch, check whether the device and its SIM(s) support Firebase PNV. This pre-check does not require user consent:
if (await fpnv.isSupported()) {
// Show your Firebase PNV explainer screen, then start the flow.
} else {
// Fall back to SMS OTP verification.
}
For per-SIM details use getVerificationSupportInfo():
final results = await fpnv.getVerificationSupportInfo();
for (final r in results) {
print('SIM ${r.simSlot} (${r.carrierId}): supported=${r.isSupported}');
}
Verify the phone number
getVerifiedPhoneNumber() runs the entire end-to-end flow: it shows the
system consent UI (Android Credential Manager), contacts the carrier through
the Firebase PNV backend, and returns the verified phone number with a signed
token:
try {
final result = await fpnv.getVerifiedPhoneNumber();
print(result.phoneNumber); // In test mode: valid country code + all zeros.
print(result.token); // Signed JWT — send this to your backend.
} on FirebasePnvException catch (e) {
switch (e.code) {
case FirebasePnvErrorCode.credentialManagerError:
// The user declined consent or Credential Manager failed.
break;
case FirebasePnvErrorCode.carrierNotSupported:
// Fall back to SMS OTP.
break;
default:
// Handle other errors (network, integrity check, etc.).
}
}
Tip: show a loading spinner before calling
getVerifiedPhoneNumber()and dismiss it when the future completes, so the 1–3 second carrier round-trip feels responsive.
Verify the token on your backend
If you use the verified phone number outside the app client, pass the token (not the raw phone number) to your backend and verify its signature there. See Verify Firebase PNV tokens.
You can also use the token as part of a sign-in flow with Firebase Authentication (via custom auth) or your own authentication system.
Error codes
FirebasePnvException.code mirrors the native
FirebasePnvStatusCodes:
| Code | Meaning |
|---|---|
carrierNotSupported |
The carrier is not supported. |
invalidDigitalCredentialResponse |
The digital credential response is invalid. |
integrityCheckFailed |
Device integrity check failed. |
preflightCheckFailed |
Preflight check failed. |
unsupportedOperation |
The API is not supported on this device. |
credentialManagerError |
Credential Manager error (includes user declining consent). |
invalidTestNumberId |
The test number ID is invalid, expired, or not found. |
testSessionAlreadyEnabled |
enableTestSession was called more than once. |
activityContextRequired |
The flow was started without a foreground Activity. |
noActivity |
The plugin is not attached to an Android Activity. |
unsupportedPlatform |
Called on a non-Android platform. |
Going to production
Once you're happy with the flow in test mode, follow the
Upgrade to production
guide (enable billing, complete OAuth brand verification, and remove the
enableTestSession call).
Example
See the example app for a complete runnable demo.
License
Libraries
- firebase_phone_number_verification
- A Flutter plugin for Firebase Phone Number Verification (Firebase PNV).
- firebase_phone_number_verification_method_channel
- firebase_phone_number_verification_platform_interface