Search code examples
iosswiftfirebasefirebase-authenticationtwitter-digits

Digits to firebase migration iOS Phone number input


I have been using digits for login via phone number. I have to migrate to firebase but there are a few things I am confused about:

My flow was: 1) User clicked on a custom button login via phone number which had action

@IBAction func loginViaDigits(_ sender: AnyObject) {
    let digits = Digits.sharedInstance()
    let configuration = DGTAuthenticationConfiguration(accountFields: .defaultOptionMask)
    configuration?.phoneNumber = "+44"
    digits.authenticate(with: self.navigationController, configuration: configuration!) { session, error in
        if error == nil {
            let digits = Digits.sharedInstance()
            let oauthSigning = DGTOAuthSigning(authConfig:digits.authConfig, authSession:digits.session())
            let authHeaders = oauthSigning?.oAuthEchoHeadersToVerifyCredentials()
            self.startActivityIndicator()
            NetworkApiCall(apiRequest: SignInApiRequest(digits_auth: authHeaders as! [NSObject : AnyObject])).run() { (result: SignInApiResponse?, error: NSError?) in
                if error != nil {
                    self.stopActivityIndicator()
                    UIUtils.showInfoAlert("Some error occurred!", controller: self)
                    return;
                }

                guard let response = result else {
                    self.stopActivityIndicator()
                    UIUtils.showInfoAlert("Some error occurred!", controller: self)
                    return;
                }

                ...
        }
    }
}

2) Basically, user clicked on login via phone number button and digits showed their popup for getting phone number and then they asked for verification code and when they were done, I would get the oauth params in my callback method and I passed them on to my server.

My question is: 1) Do I need to build both phone number input and verification code input screens myself or firebase is providing them like digits did?

2) If someone has actually migrated this kind of flow already, some pointers would be very helpful.

As suggested by Lazy King, I am trying to use FirebaseAuthUI, but my AppDelegate seems to be missing some function:

My AppDelegate changes for Firebase:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Pass device token to auth
    Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.prod)
}

func application(_ application: UIApplication,
                 didReceiveRemoteNotification notification: [AnyHashable : Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if Auth.auth().canHandleNotification(notification) {
        completionHandler(.noData)
        return
    }
    // This notification is not auth related, developer should handle it.
}

But I still keep getting this error: Error Domain=FIRAuthErrorDomain Code=17054 "If app delegate swizzling is disabled, remote notifications received by UIApplicationDelegate need to be forwarded to FIRAuth's canHandleNotificaton: method."


Solution

  • You can use FirebaseAuth UI or design a UI for your own. For one of my project I used FirebaseAuth UI. Here is step by step:

    1. Add FireBase Auth and Auth UI pod 'Firebase/Auth', '~> 4.0.0' and pod 'FirebaseUI/Phone', '~> 4.0'

    2. In Appdelegate file register for push notification, this is mandatory. Google user push notification for first verification. Add this line on didRegisterForRemoteNotificationsWithDeviceToken:

      Auth.auth().setAPNSToken(deviceToken, type:AuthAPNSTokenType.prod)//.sandbox for development
      
    3. You also need set up Google notification on you Firebase console

    4. on Phone log in button function

      var uiAuth = FUIAuth.defaultAuthUI() ;
      
      uiAuth?.delegate = self;
      var phoneVC = FUIPhoneAuth(authUI: uiAuth!)
      
      uiAuth.providers = [phoneVC];
      phoneVC.signIn(withPresenting: self)
      
    5. implement delegate function

    6. in Appdelegate receive notification function add code

       if Auth.auth().canHandleNotification(userInfo) {
          completionHandler(UIBackgroundFetchResult.noData)
          return
      }
      

    If you use iOS 10 or later then

    @available(iOS 10.0, *)
    internal func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    
        let userInfo = response.notification.request.content.userInfo
        if Auth.auth().canHandleNotification(userInfo) {
            completionHandler()
            return
        }
    
        completionHandler()
    }
    

    Hope it will work.