Firebase-ios-sdk: [Firebase/Auth][I-AUT000015] The UIApplicationDelegate must handle remote notification for phone number authentication to work (7.4.0, SwiftUI)

Created on 26 Jan 2021  路  7Comments  路  Source: firebase/firebase-ios-sdk

Step 0: Are you in the right place?

Yes. And thank you for building this, Firebase makes for delightful realtime experiences.

[REQUIRED] Step 1: Describe your environment

  • Xcode version: 12.3
  • Firebase SDK version: 7.4.0
  • Installation method: CocoaPods
  • Firebase Component: Auth

[REQUIRED] Step 2: Describe the problem

When I try to call PhoneAuthProvider.provider().verifyPhoneNumber, it tells me that The UIApplicationDelegate must handle remote notification for phone number authentication to work

I am using SwiftUI with UIApplicationDelegateAdaptor. I have verified that I followed all of the instructions from the official documentation and with these steps:

  1. Create a Firebase project and set up PhoneNumber Auth

  2. Add your iOS app to the Firebase project, download and add GoogleService-Info.plist to your project

  3. In Xcode, select the application target and enable the following capabilities:

  4. Push notifications
    Background modes > Remote notifications
    Create and register an APNS authentication key on the Apple developer portal

  5. Upload the key to Firebase (under Project Settings > Cloud messaging in the Firebase Console)

  6. Add the Firebase project's reversed client ID to app's URL schemes

  7. In Info.plist, set FirebaseAppDelegateProxyEnabled to NO

  8. Implemented the AppDelegate as follows:

*Note that we're also using Messaging which we also forward notifications to, no problem. I also tried removing all of the Messaging integration to see if there was interference, but it didn't resolve the issue. *

Relevant Code:

  func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("\(#function)")
    Messaging.messaging().apnsToken = deviceToken
    Auth.auth().setAPNSToken(deviceToken, type: .sandbox) // Ive tried prod and just setting it directly
    print(deviceToken)
  }

  func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print("\(#function)") // This never prints, nor breakpoint hit
    if Auth.auth().canHandleNotification(userInfo) {
        completionHandler(.noData)
        return
    }
    Messaging.messaging().appDidReceiveMessage(userInfo)
  }

  func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
      print("\(#function)")
      if Auth.auth().canHandle(url) {
        return true
      }
      return false
    }
  var body: some Scene {
    WindowGroup {
      ContentView(viewModel: .init(context: context))
        .environmentObject(context)
        .onOpenURL { url in
          print("Received URL: \(url)")
          Auth.auth().canHandle(url)
        }
    }

Digging further, I found a reference to this codepath in Firebase which generates this warning: https://github.com/firebase/firebase-ios-sdk/blob/31a2acb7497eaaeae38b7ceb17edcab09d7f2866/Firebase/Auth/Source/FIRAuthNotificationManager.m#L107-L120

So I put this code right before the call to PhoneAuthProvider to see if my app delegate responds to the selector, and it returns true:

let responds = UIApplication.shared.delegate?.responds(to: #selector(UIApplicationDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)))
      print("Responds? \(responds)")

So, the app delegate, from within my application's context, is able to verify that selector.

auth

All 7 comments

@chrysb Sorry you experience the issue. It looks like UIApplicationDelegateAdaptor affects the way respondsToSelector: for the UIApplication delegate works which can affect Firebase SDKs functionality. We are working on designing a long term fix and will look for a workaround for the current issue.

In the meanwhile the only workaround I can see is to avoid using UIApplicationDelegateAdaptor so far.

@maksymmalyhin Thanks, I'm glad I'm not crazy... I bashed my head for a while :)

I look forward to the fix or workaround 鈥斅燽ecause now we're going to have to fallback to using a different Auth provider and implementing our own phone number verification flow using Twilio 馃槄

Appreciate your super fast response!

@chrysb I tried to follow the particular steps you shared but was not able to reproduce the issue you have. I guess there are some missing pieces not described in the ticket. Could you please share a sample project where the issue is reproducible so we can help you with a workaround for your case and make sure it is covered by our intended fix?

Most of the issue we discovered so far are related to interacting UIApplicationDelegateAdaptor with Firebase app delegate swizzler, so I guess your issue may be slightly different.

I would also suggest to check https://github.com/firebase/firebase-ios-sdk/blob/master/docs/firebase_in_libraries.md and presence of messages like the following:

objc[40943]: Class FIRApp is implemented in both
~/Library/Developer/Xcode/DerivedData/FrameworkTest-apqjxlyrxvkbhhafhaypsbdquref/Build/Products/Debug-iphonesimulator/DynamicFramework.framework/DynamicFramework
(0x10b2a87f8) and
~/Library/Developer/CoreSimulator/Devices/4821F959-24A6-4D78-A102-4C5703103D99/data/Containers/Bundle/Application/F017D210-113A-4DAF-9E17-BDE455E71E06/FrameworkTest.app/FrameworkTest
(0x10ad2d348). One of the two will be used. Which one is undefined.

Hi @maksymmalyhin,

Thanks for looking into this! I'm not sure I'll have the time to create a sample project to repeat all of these steps, but I'll certainly be happy to test the new update and see if the issue is resolved. For now, we're going to stick with a different default auth and verify phone numbers via Twilio.

Loving Firebase! Keep up the great work :)

@chrysb I've encounter the same issue today. I think you probably used:
init() { FirebaseApp.configure() }

instead of
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FirebaseApp.configure() return true }
I've got the same error if I missed didFinishLaunchingWithOptions.

@chrysb I've encounter the same issue today. I think you probably used:
init() { FirebaseApp.configure() }

instead of
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FirebaseApp.configure() return true }
I've got the same error if I missed didFinishLaunchingWithOptions.

You're right - I am calling FirebaseApp.configure() somewhere else. Thanks for the tip!

Was this page helpful?
0 / 5 - 0 ratings