Description
Description
PhoneAuthProvider.verifyPhoneNumber fails immediately with notificationNotForwardedError
on a real device (TestFlight release build), on the very first attempt after a cold app launch
(not a session-cache artifact — tested explicitly).
Root cause identified (source read)
AuthNotificationManager.checkNotificationForwarding() sends a local fake probe notification
via application.delegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
and waits kProbingTimeout = 1.0 second for it to be routed back through
AuthNotificationManager.canHandle(notification:). If this 1s local round-trip fails, the SDK
throws directly — PhoneAuthProvider.internalVerify never reaches the reCAPTCHA fallback
(AuthRecaptchaVerifier switch is unreachable).
What we've verified as correct (ruling out app misconfiguration)
- APNs Auth Key correctly uploaded (Cloud Messaging), correct Key ID/Team ID
- Push Notifications capability enabled on App ID
aps-environment = production in release entitlements
- Phone provider enabled, SMS region policy allows the test region
- API key: Identity Toolkit + Token Service APIs allowed, no blocking application restriction
REVERSED_CLIENT_ID correctly registered as URL scheme
FirebaseAppDelegateProxyEnabled absent (swizzling enabled by default)
- Single
UIApplicationDelegate, no conflicting delegate, no SceneDelegate interference
(confirmed GULSceneDelegateSwizzler only swizzles scene:openURLContexts:, never
notification methods)
didReceiveRemoteNotification has the exact expected signature (with
fetchCompletionHandler), matches the selector Firebase looks for byte-for-byte
- APNs device token IS received (
FirebaseMessaging.instance.getAPNSToken() returns non-null
at call time — confirmed via on-device logging)
- App Check (App Attest) registered, monitoring mode (not enforced)
appVerificationDisabledForTesting never set (would be test-only anyway)
- Tested explicitly on FIRST attempt after full app kill+relaunch — not a repeated-session
cache issue (session cache at AuthNotificationManager.swift:45,91 was considered and ruled
out this way)
Suspicion
The 1-second timeout for a purely local delegate round-trip (no network involved) may be too
short on some real devices/launch conditions, and there's no retry once cached as failed for
the session — but here it fails even on the very first attempt, suggesting either the timeout
is sometimes insufficient on cold launch, or another condition prevents
canHandle(notification:) from being reached in time.
Environment
- firebase_auth: 5.7.0 (FlutterFire)
- Firebase iOS SDK: vendored via CocoaPods (version bundled with firebase_auth 5.7.0)
- Device: iPhone 13, iOS 26.6.2, real device via TestFlight (release build)
- Flutter stable
Steps to reproduce
- Real device, release/TestFlight build
- Fresh app launch (kill previous instance first)
- Navigate directly to phone sign-in, enter valid number, tap send — first and only action
verifyPhoneNumber completion handler receives notificationNotForwardedError immediately
Expected
Either the probe succeeds, or a graceful fallback to reCAPTCHA occurs.
Reproducing the issue
No response
Firebase SDK Version
5.7.0
Xcode Version
15.4
Installation Method
CocoaPods
Firebase Product(s)
Authentication
Targeted Platforms
iOS
Relevant Log Output
If using Swift Package Manager, the project's Package.resolved
Expand Package.resolved snippet
Replace this line with the contents of your Package.resolved.
If using CocoaPods, the project's Podfile.lock
Expand Podfile.lock snippet
Replace this line with the contents of your Podfile.lock!
Description
Description
PhoneAuthProvider.verifyPhoneNumberfails immediately withnotificationNotForwardedErroron a real device (TestFlight release build), on the very first attempt after a cold app launch
(not a session-cache artifact — tested explicitly).
Root cause identified (source read)
AuthNotificationManager.checkNotificationForwarding()sends a local fake probe notificationvia
application.delegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)and waits
kProbingTimeout = 1.0second for it to be routed back throughAuthNotificationManager.canHandle(notification:). If this 1s local round-trip fails, the SDKthrows directly —
PhoneAuthProvider.internalVerifynever reaches the reCAPTCHA fallback(
AuthRecaptchaVerifierswitch is unreachable).What we've verified as correct (ruling out app misconfiguration)
aps-environment = productionin release entitlementsREVERSED_CLIENT_IDcorrectly registered as URL schemeFirebaseAppDelegateProxyEnabledabsent (swizzling enabled by default)UIApplicationDelegate, no conflicting delegate, no SceneDelegate interference(confirmed
GULSceneDelegateSwizzleronly swizzlesscene:openURLContexts:, nevernotification methods)
didReceiveRemoteNotificationhas the exact expected signature (withfetchCompletionHandler), matches the selector Firebase looks for byte-for-byteFirebaseMessaging.instance.getAPNSToken()returns non-nullat call time — confirmed via on-device logging)
appVerificationDisabledForTestingnever set (would be test-only anyway)cache issue (session cache at
AuthNotificationManager.swift:45,91was considered and ruledout this way)
Suspicion
The 1-second timeout for a purely local delegate round-trip (no network involved) may be too
short on some real devices/launch conditions, and there's no retry once cached as failed for
the session — but here it fails even on the very first attempt, suggesting either the timeout
is sometimes insufficient on cold launch, or another condition prevents
canHandle(notification:)from being reached in time.Environment
Steps to reproduce
verifyPhoneNumbercompletion handler receivesnotificationNotForwardedErrorimmediatelyExpected
Either the probe succeeds, or a graceful fallback to reCAPTCHA occurs.
Reproducing the issue
No response
Firebase SDK Version
5.7.0
Xcode Version
15.4
Installation Method
CocoaPods
Firebase Product(s)
Authentication
Targeted Platforms
iOS
Relevant Log Output
If using Swift Package Manager, the project's Package.resolved
Expand
Package.resolvedsnippetReplace this line with the contents of your Package.resolved.If using CocoaPods, the project's Podfile.lock
Expand
Podfile.locksnippetReplace this line with the contents of your Podfile.lock!