4

When i want to use sms auth with firebase the app fails only on iOS

The APN certificate is alredy configured on firebase and FirebaseAppDelegateProxyEnabled is NO in Info.plist. The error is occuring during the verifyPhoneNumber method.

Here is the flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel unknown, v1.7.0, on Mac OS X 10.14.5 18F132, locale en-PE)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 10.2.1)
[✓] iOS tools - develop for iOS devices
[✓] Android Studio (version 3.4)
[!] IntelliJ IDEA Ultimate Edition (version 2019.1)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] VS Code (version 1.36.1)
[✓] Connected device (1 available)

Here is my code

void sendSms(String fullNumber) {
    FirebaseAuth.instance.verifyPhoneNumber(
      phoneNumber: fullNumber,
      timeout: Duration(minutes: 1),
      verificationCompleted: (AuthCredential phoneAuthCredential) async {
        _smsController?.add('loading');
        FirebaseUser firebaseUser = await FirebaseAuth.instance
            .signInWithCredential(phoneAuthCredential);
        _verifyUser(firebaseUser);
      },
      verificationFailed: (err) {
        print(err.message);
        print(err.code);
        _smsController?.add('UNKNOWN_ERROR');
      },
      codeSent: (verificationId, [forceResendingToken]) {
        _verificationId = verificationId;
        _smsController?.add('code_sent');
      },
      codeAutoRetrievalTimeout: (verificationId) {},
    );
  }

And the error messages:

flutter: If app delegate swizzling is disabled, remote notifications received by UIApplicationDelegate need to be forwarded to FIRAuth's canHandleNotificaton: method.

flutter: verifyPhoneNumberError

Enzo Lizama
  • 1,214
  • 1
  • 14
  • 23

3 Answers3

2

Best Available Solution AppDelegate.swift:

import UIKit
import Flutter
import FirebaseAuth
import FirebaseMessaging

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [. 
UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: 
launchOptions)
}

// https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
// https://firebase.google.com/docs/cloud-messaging/ios/client#token-swizzle-disabled
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Pass device token to auth
    Auth.auth().setAPNSToken(deviceToken, type: .unknown)

    // Pass device token to messaging
    Messaging.messaging().apnsToken = deviceToken

    return super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}

// https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
// https://firebase.google.com/docs/cloud-messaging/ios/receive#handle-swizzle
override func application(_ application: UIApplication,
                          didReceiveRemoteNotification notification: [AnyHashable : Any],
                          fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // Handle the message for firebase auth phone verification
    if Auth.auth().canHandleNotification(notification) {
        completionHandler(.noData)
        return
    }

    // Handle it for firebase messaging analytics
    if ((notification["gcm.message_id"]) != nil) {
        Messaging.messaging().appDidReceiveMessage(notification)
    }

    return super.application(application, didReceiveRemoteNotification: notification, fetchCompletionHandler: completionHandler)
}

// https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
override func application(_ application: UIApplication, open url: URL,
                          options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
    // Handle auth reCAPTCHA when silent push notifications aren't available
    if Auth.auth().canHandle(url) {
        return true
    }

    return super.application(application, open: url, options: options)
   }
}
Rachit Vohera
  • 707
  • 7
  • 10
0

Solution :

I found this in flutter repository and currently works.

Replace the current firebase_auth version with

firebase_auth:
    git:
      url: https://github.com/collinjackson/plugins.git
      ref: 441417c2fed0ff26bf84a49ab2c5ffd2aa5487de
      path: packages/firebase_auth
Enzo Lizama
  • 1,214
  • 1
  • 14
  • 23
0

As I am using firebase messaging and phone auth in my flutter project, and I also facing the same issue for FCM notification with Image support. In ImageNotification Project

// NotificationService.h

#import <UIKit/UIKit.h>

And,

// NotificationService.m
    
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
  if ([[FIRAuth auth] canHandleURL:url]) {
    return YES;
  }
  // URL not auth related; it should be handled separately.
    return NO;
}

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
  for (UIOpenURLContext *urlContext in URLContexts) {
    [FIRAuth.auth canHandleURL:urlContext.URL];
    // URL not auth related; it should be handled separately.
  }
}

This is working for me. Thanks.