The Complete Guide to Firebase Phone Auth for iOS
Firebase’s iOS SDK is typically well documented, however I realised that it was lacking for Phone Auth after a large struggle implementing it myself.
I decided to write this guide to help future developers and save them from the reading around, and trial and error I had to endure!
Prerequisites
All you will need is a Firebase and Xcode project ready to go!
Make sure you have Firebase, Firebase Auth, and Firebase Messaging added as package dependencies in Xcode.
Stage One: Setup Firebase and the APN service
Step One
The first step is simple: enable Phone Auth in the Firebase Console:
You can also add some testing phone numbers and verification codes here.
Step Two: Enabling slient notifications (APN Key setup)
Firebase requires either reCAPTCHA or a silent push notification (notifications sent through Apple’s servers, but not appearing to the user) to authorise the request to send an OTP code (for spam prevention).
I would recommend ensuring both work for a smooth user experience and for a fallback in case the push notification is not received.
We will also implement user facing notification handling for Firebase Cloud Messaging at the same time.
First, head over to Apple Developer > Keys, Certificates, and Identities
Add a key, give it a name, and check the box for Apple Push Notifications service. Download the key and save it securely on your computer.
Now, head over to the Firebase console.
and upload the APN key here, under Project Settings (gear icon) > Cloud Messaging.
Step Three: Enabling silent notifications (continued!)
Now head over to Xcode:
Add capabilities for Background Modes (check Remote Notifications), and Push Notifications.
Finally, head back to the Project Info page:
And add a URL scheme. Copy the URL from the GoogleService-Info.plist
. You want the one under REVERSED_CLIENT_ID
.
Stage Two: Adding callbacks for Remote Notification
Step One: Disabling method swizzling
Firebase usually hooks into these callbacks in the App Delegate automatically, however I have found that it does not work with SwiftUI lifecycle apps. Therefore we will implement the callbacks ourselves.
Head into the Custom Target Properties under Info and add a key for FirebaseAppDelegateProxyEnabled
, with type Boolean
, and value false
or 0
.
Step Two: Setting up AppDelegateAdaptor
Now it’s time to get into the meat of this task. The following code snippets are based around a SwiftUI lifecycle app but can easily be adapted for UIKit.
- Create a class subclassing
UIApplicationDelegate
, and callFirebaseApp.configure()
as required. - Then, pipe the class through to SwiftUI with a
@UIApplicationDelegateAdaptor
as shown.
Step 3: Implement App Delegate callbacks
Head into your AppDelegate
and:
- Set the delegates for the
UNUserNotificationCenter
and Firebase Messaging client as shown (you may get compiler errors, we will deal with these shortly) - Request notification access (not necessary for silent notifications in recent versions of iOS, so feel free to not implement this)
- Implement the
didRecieveNotification
handler as shown. If the notification is for Firebase Auth, do not pass on to Messaging. (Although not strictly necessary, doing this will allow you to use Cloud Messaging outside of Firebase Auth)
Step 4: Implement App Delegate Delegates
The UNNotificationCenterDelegate
and Messaging Delegate are implemented through extensions to help separate the code.
- Add the extension for the
UNUserNotificationCenterDelegate
and implement the callbacks for presenting and receiving notifications - Add the callback for
didRegisterForRemoteNotificationsWithDeviceToken
and pass the APNS token to Firebase Auth and Messaging. This is to verify that the notification recieved was intended for this device. Make sure to choose type:.unknown
otherwise you may get some unexpected errors as the type will be different for debug and release builds. - Finally, add the extension for the Firebase MessagingDelegate and the function e to share the token throughout the app.
Stage 3: Sign in users
We are now ready to sign in users. I like to implement the following methods in an ObservableObject
injected via .environmentObject
at the root view, but feel free to implement these as you please.
- Implement the
sendSMS
function. Call.verifyPhoneNumber
and pass the error through with an escaping closure. Remember to store theverificationID
somewhere (UserDefaults is appropriate) so that the request can be authenticated. - Implement the
signIn
function. Grab theverificationID
we saved earlier and create the Firebase credential with this and the OTP code provided by the user. Callauth().signIn
and pass the error through in an escapting closure.
Congratulations!
That is all the code required to implement Firebase Phone Auth on iOS. A bit of an involved process, but one rightfully so to prevent scam.
I hope this guide has cleared things up and made your journey implementing Firebase that little bit easier. Thanks for checking it out!
Please check out the Firebase Docs on Phone Auth and Cloud Messaging for more information:
— Oliver.