firebase-ios-sdk icon indicating copy to clipboard operation
firebase-ios-sdk copied to clipboard

Client library is throwing the wrong error on .verifyPhoneNumber completion

Open tssm opened this issue 2 years ago • 16 comments

Description

We successfully implemented password authentication through Firebase, and now we are adding SMS as a second factor. It correctly works on our web app, but on iOS we are getting the following error (code 17006) on the .verifyPhoneNumber callback:

NSLocalizedDescription=The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section. FIRAuthErrorUserInfoNameKey=ERROR_OPERATION_NOT_ALLOWED

Whatever we are doing wrong, it is hard to debug because as I mentioned before, we successfully implemented it on the web app, so we already have both password authentication and SMS as second factor enabled in our Firebase project. What's more weird, this always happen when the app is released on TestFlight, but only sometimes when we run a build directly from Xcode on a real device.

Here is the minimum code that produces the error, I also tried the async API with the same result:

Auth.auth().signIn(withEmail: email, password: password) { auth, error in
    if let error = error as? NSError {
        if error.code == AuthErrorCode.secondFactorRequired.rawValue {
            let resolver = error.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
            if let hint = resolver.hints.first(where: { $0.factorID == PhoneMultiFactorID }) {
                PhoneAuthProvider
                    .provider()
                    .verifyPhoneNumber(
                        with: hint as! PhoneMultiFactorInfo,
                        uiDelegate: nil,
                        multiFactorSession: resolver.session
                    ) { verificationId, error in
                        if let error = error {
                            print(error) // <- this is being hitted
                        } else if let verificationId = verificationId {
                            print("verified!!!!!!!!") // <- this happens some times on sandbox, never on TestFlight
                        } else {
                            print("errror")
                        }
                    }
            }
        }
    }
}

We are using SwiftUI 2, targeting iOS 15, so swizzling is disabled. This is our bare minimum implementation of UIAplicationDelegate:

final class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()

        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Auth.auth().setAPNSToken(deviceToken, type: .unknown)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if Auth.auth().canHandleNotification(notification) {
            completionHandler(.noData)
            return
        }
    }

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        let sceneConfig = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
        sceneConfig.delegateClass = SceneDelegate.self
        return sceneConfig
    }
}

Our UIWindowSceneDelegate is also pretty slim:

final class SceneDelegate: NSObject, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        for urlContext in URLContexts {
            Auth.auth().canHandle(urlContext.url)
        }
    }
}

We are using an APNs authentication key, and both the Push notifications and Remote notifications background mode were added as capabilities on Xcode. If we remove the latter, we still get the same error

Reproducing the issue

No response

Firebase SDK Version

10.5.0

Xcode Version

14.2

Installation Method

Swift Package Manager

Firebase Product(s)

Authentication

Targeted Platforms

iOS

Relevant Log Output

No response

If using Swift Package Manager, the project's Package.resolved

We actually used the built-in Xcode package manager, so we don't have a Package.resolved file

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet

Replace this line with the contents of your Podfile.lock!

tssm avatar Feb 17 '23 16:02 tssm

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

google-oss-bot avatar Feb 17 '23 16:02 google-oss-bot

Thanks for reaching out, @tssm. Based on the error message you shared, this typically occurs when the Auth provider you'll be using is disabled in the console. With this, could you double-check first if the phone auth provider is already enabled in your console?

rizafran avatar Feb 20 '23 15:02 rizafran

Thanks for the answer @rizafran. Both email authentication and multifactor are enabled in the Firebase console. Please note that, as I mentioned before, the issue only happens on iOS, our customers are able to log in and receive an SMS as second factor when they log in on the web app.

Today I managed to make it work, somehow. Here are the details:

  1. Swizzling is still disabled by using the GoogleUtilitiesAppDelegateProxyEnabled property on Info.plist
  2. We removed the Push notifications capability of our Xcode project, but kept the implementations of application(_:didReceiveRemoteNotification:fetchCompletionHandler:): in UIApplicationDelegate and scene(_:openURLContexts:) in UIWindowSceneDelegate, otherwise the app crashes during the SMS verification step. Please notice that I deleted application(_:didRegisterForRemoteNotificationsWithDeviceToken:) from the UIApplicationDelegate implementation, but SMS verification still works!
  3. We added a newly generated APNs authentication key to the Firebase console
  4. The legacy Cloud Messaging API is enabled on the console, V1 is disabled. No idea if this makes any difference

Based on this behaviour, I guess the issue is related to the push notifications setup on a pure SwiftUI app, making only the reCAPTCHA method reliable. We would like to avoid showing the reCAPTCHA as much as possible, though.

As an extra, it's weird that we still need to add push notifications logic to the UIApplicationDelegate event when they aren't working at all.

Hopefully this helps to clarify the issue

tssm avatar Feb 20 '23 16:02 tssm

Thanks for the info, @tssm. The behavior you're encountering might be unrelated to the error as it's about the disabled Auth provider in the console. I'm curious if you're getting any other errors aside from the error you shared above? Also, could you confirm if you've disabled the FirebaseAppDelegateProxyEnabled in your Info.plist file as stated here? I'm not sure if this also applies, but it is noted on the docs as well that SwiftUI apps should use the UIApplicationDelegateAdaptor or NSApplicationDelegateAdaptor property wrappers to provide a type corresponding to the appropriate app delegate protocol.

rizafran avatar Feb 23 '23 18:02 rizafran

We don't see any other errors. I can confirm swizzling is disabled, although we are using GoogleUtilitiesAppDelegateProxyEnabled in our Info.plist instead of FirebaseAppDelegateProxyEnabled. I tried with the latter, but the result is the same:

[GoogleUtilities/AppDelegateSwizzler][I-SWZ001011] App Delegate Proxy is disabled.

So I'm not sure if there's any difference between both keys. And yes, I can confirm we are using an UIApplicationDelegate, and that we set it with UIApplicationDelegateAdaptor

tssm avatar Feb 24 '23 08:02 tssm

Sorry for the late revert. Our engineers have been notified about this issue. This is internally tracked in b/279781096.

rizafran avatar Apr 26 '23 18:04 rizafran

Cool guys, thank you!

tssm avatar Apr 27 '23 11:04 tssm

I'm having a similar issue. We have Email enabled as a Sign-in Provider, all other providers disabled, and SMS Multi-factor Authentication enabled. Signing in works fine on Android, but on iOS we receive the 17006 error above. If we enable Phone as a Sign-in Provider, we can successfully verifyPhoneNumber and receive the SMS.

dominique-um avatar May 03 '23 20:05 dominique-um

Im having the same problem on Firebase version 10.12.0 iOS pure SwiftUI. @tssm Did you resolve this? @rizafran ?

otymartin avatar Jul 25 '23 01:07 otymartin

@otymartin kind of, I described the workaround here. I guess you can ignore steps 3 and 4, but keep in mind the result of this is the user will always see the CAPTCHA, quite annoying, but at least they can log in

tssm avatar Jul 26 '23 11:07 tssm

This issue persists: the only way to make SMS two-factor authentication work on iOS, when following the Firebase documentation, is to enable ‘Phone’ as a sign-in provider. This requirement applies only if using APNs instead of reCAPTCHA. If using reCAPTCHA, the normal flow works fine, and you can use SMS two-factor authentication without having ‘Phone’ as a sign-in provider in the Firebase Console.

jordanebelanger avatar Jul 23 '24 20:07 jordanebelanger

Any difference in behavior with Firebase 11.0.0?

paulb777 avatar Aug 09 '24 23:08 paulb777

Any difference in behavior with Firebase 11.0.0?

I cannot say as I can no longer login at all on v11 (v10 works but with the previously mentioned problem).

I am almost 99% sure we are hitting this specific new issue https://github.com/firebase/firebase-ios-sdk/issues/13479

edit: I did one test and disabled the phone auth provider (keeping SMS mfa activated), this leads to the following error: "The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section"

jordanebelanger avatar Aug 12 '24 12:08 jordanebelanger