I'm currently implementing firebase phone Authentication, and can successfully implement the phone authentication using the firebase UI without swizzling, but from my research it seems that implementing firebase phone authentication without swizzling requires the user to allow notifications. I know that firebase sends a silent notification that does not need to be approved through allowing notifications but it seems the only way to get that notification without swizzling is to ask the user to allow notification. Does anyone know how or if its possible to do this without swizzling and without asking the user for notification permissions?
I have added to push notification certificates to firebase, and have added all the needed function listed in the firebase phone ui docs.
Without asking the user for to allow notifications this function listed from the phone auth docs does not get called (the user also has to select allow)
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Pass device token to auth
Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenTypeProd)
// Further handling of the device token if needed by the app
// ...
}
If this functions is not called the setAPNSToken is not set, I will not get the silent notification to continue with phone auth, and I will get the generic error
Authentication error: There seems to be a problem with your project's
Firebase phone number authentication set-up, please make sure to
follow the instructions found at
https://firebase.google.com/docs/auth/ios/phone-auth
I went ahead and disabled method swizzling as stated in the Firebase docs and then implemented all the required methods, the solution was that I needed to go the Capabilities of the app and then make sure Background Modes as well as Push Notifications (this was already enabled) were enabled. Then under Background Modes I had to enable Remote notifications.
Then I had to delete the app from my device and reinstall. This solved my issue and called the necessary functions for registering for notifications.
Related
I'm wondering what's happening behind the scenes when registering ios applications for push notifications and how the ios device receives device-token in application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) callback. I need to know the complete scenario and protocol communication.
So this all works like this:
1) Your app asks to be registered with APNs.
2) On successful registration, APNs sends an app-specific device token to the device.
3) The system delivers the device to your app by calling a method in your app delegate.
For more information, check these links :-
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/HandlingRemoteNotifications.html
https://nshipster.com/apns-device-tokens/
the most related things I could find are:
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html
https://developer.apple.com/library/archive/technotes/tn2265/_index.html
what I could understand is that most of the work is done by os that establishes a direct and persistent connection to apple's servers. no more information about any protocols or request-responses.
We are currently in the process of preparing an update for an exisiting app, which provides push notifications via Firebase, which uses a token-based APNs connection.
Due to changes in the backend, we want to transition to OneSignal, which is certificate based.
Since the app is going to be released as an update, we want to maintain pushes via Firebase during a transition period, while updated versions should be able to receive pushes via OneSignal.
My question is: can I use both at the same time for one App-ID? Or are they going to interfere with each other?.
Apple's docs mention that
To send notifications, your provider server must establish either token-based or certificate-based trust with APNs using HTTP/2 and TLS.
but don't say anything about implementing both at the same time.
You actually can use both of them in parallel.
You also can generate 2 certificates and use them in parallel as well.
You also can use a single certificate/token from many places.
There are no any restrictions with this - certificate/token is only used to identify who you are, your App ID.
Since you've mentioned "receive pushes via OneSignal" I am assuming you are talking about iOS app, but I believe this is more of a backend problem. Because on iOS all you have to do is
register for push notifications via project settings
ask for permissions (Info.plist)
handle in appDelegate func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) and func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
setup correctly the developer portal for your project (certificates, permisions etc.)
All the push notifications that are coming to the device are coming from APNs, so your app cares neither about the Firebase or the OneSignal.
I believe your app will have OneSignal SDK in it, not the Firebase after the update.
So I think you need to handle the sending of push notifications via Firebase and OneSignal on the server during the transition period. Your server needs to communicate with both of those services at the same time. APNs will handle the rest of the delivery for you.
You can always use sandbox servers for a tryout before production.
I need to refresh push token if user don't run app for long time. I tried to use background mode and application:performFetchWithCompletionHandler:
method. Inside this method I call - registerUserNotificationSettings:(UIUserNotificationSettings )notificationSettings. And then I expect that didRegisterUserNotificationSettings (UIUserNotificationSettings)notificationSettings will be called but this not happen. Is there any way to register in APNS without running app?
Simple Answer is No
APNs can issue a new device token for a variety of reasons:
User installs your app on a new device
User restores device from a backup
User reinstalls the operating system
Other system-defined events
As a result, apps must request the device token at launch time, as described in APNs-to-Device Connection Trust and Device Tokens. For code examples, see Registering to Receive Remote Notifications.
Apple Documentation : https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html
Our app uses Firebase phone auth. The App Store review has rejected the app due to pushes being required:
Guideline 4.5.4 - Design - Apple Sites and Services
We noticed that your app requires push notifications in order to function.
Specifically, we noticed if the Push Notifications setting was not enabled on our device, we encountered an error message after entering our phone number within the app.
Next Steps
Push notifications must be optional and must obtain the user's consent to be used within the app.
And they've also attached the screenshot that depicts Firebase error "Remote notifications and background fetching need to be set up for the app [...]"
Firebase documentation states that APNs notifications are absolutely required for phone auth to function:
https://firebase.google.com/docs/auth/ios/phone-auth
To use phone number authentication, your app must be able to receive APNs notifications from Firebase. When you sign in a user with their phone number for the first time on a device, Firebase Authentication sends a silent push notification to the device to verify that the phone number sign-in request comes from your app. (For this reason, phone number sign-in cannot be used on a simulator.)
However App Store review guidelines state that Push Notifications must not be required in order for the app to function: https://developer.apple.com/app-store/review/guidelines/
4.5.4 Push Notifications must not be required for the app to function, and should not be used for advertising, promotions, or direct marketing purposes or to send sensitive personal or confidential information.
Users need to sign in before they can use the app (the app is about sending digital GIF invitations to your guests and sharing photos), which is why Push Notifications are basically required for the app to function, if the sign in method is Firebase phone auth.
We have tested the app a lot, and the authentication works without a problem when push notifications are enabled (on real devices, both in distribution Ad Hoc builds with production environment and development builds with sandbox environment).
Come to think of it, how did App Review team even disable Push Notifications? The notification center setting does not stop actual pushes, it just doesn't display them.
We have tested with this setting off, and firebase phone auth works fine, pushes are still coming through as expected.
I am very surprised with this issue, as Firebase is a huge service provider. Did anyone else encounter this issue?
Are there plans to remove APNs requirement for phone auth? Is there maybe some other way to use Firebase phone auth without pushes?
Firebaser here. We have released an updated Firebase Auth SDK, 4.2.0, as Leetmory mentioned, which should hopefully resolve these issues going forward.
The issue was caused by the fact that the Firebase Auth SDK using APNs to validate the request - this is to minimize the risk of SMS spam abuse or similar. The validation uses a silent APNs notification, so doesn't require explicit user consent for iOS 8 and above. However, this still failed if APNs was completely disabled, as in this review case.
The 4.2.0 release introduced the facility to use a reCAPTCHA prompt inside an SFSafariViewController (or webview for older iOS) to prevent abuse if APNs isn't available. We don't expect this to happen very much, but it accounts for the unusual state encountered here. It also enables support for testing Firebase Phone Auth on the simulator!
You'll notice there is a new uiDelegate parameter on the verifyPhoneNumber method. In most cases you wont need to use this, but it is part of the fallback verification.
What you will need to do, if you haven't already, is add the REVERSED_CLIENT_ID (from the GoogleService-Info.plist) as a custom URL scheme. This will allow the reCAPTCHA view to return validation to your app.
There is a gotchas to be aware of in the current version though:
In the callback from verifyPhoneNumber you'll need to redispatch to the main thread, using DispatchQueue.main.async {} - this will be fixed in the next version of Firebase Auth!
Other than that, things should work as normal! We definitely recommend supporting silent push where ever possible to ensure the best user experience.
For a full walk through, see the full Phone Auth developer guide.
UPD: Firebase 4.2.0 has rolled out, which fixes the issue. You will need to add your reverse-client-id which looks something like this: com.googleusercontent.apps.123456-abcdefg99 to URL schemes in your Info.plist, and you are set.
To find this
value, open the GoogleService-Info.plist configuration file, and look for the
REVERSED_CLIENT_ID key.
Firebase support has confirmed this bug and has given the response to this issue:
to me
Thank you for the detailed information Leet. This is indeed an odd situation, and our Phone Auth engineers are taking a look. I'll get back to you as soon as I have an answer.
Best,
Jeff
to me
Hi Leet,
Our engineers are working internally on a long-term fix for this, but in the meantime, would like to meet with you to see if we can figure out a workaround.
It appears that there is indeed a bug in Firebase phone auth / Firebase UI.
I contacted Firebase support and here's an excerpt:
In terms of the concern around users disabling push notifications - Disabling push notification for the app by the user does not normally prevent users from signing in using their phone number with Firebase Auth. Our requirement is that the app must set up and enable push notification, not the user. Regardless of if the user accepts or declines your app's push notification prompt phone auth will continue to work since we use silent pushes that don't require any action from the user.
I researched further and found that silent push notifications do indeed arrive to the device even when the user explicitly disables push notifications. To disable silent push notifications you would need to go to Settings -> Your App -> Background Refresh to disable it. See Is Silent Remote Notifications possible if user has disabled push for the app?
So you can tell the App Store Review team that your login will only work when Background Refresh is enabled. I don't believe this violates their terms.
EDIT
After some testing, it appears that phone auth can work when Background Refresh is disabled. However, it works for me because Firebase already has access to my APNS device token. I have found no way to disassociate my device token from Firebase - they provide no API for it. This unfortunately makes it impossible to test the scenario where a new user disables Background Refresh and Remote Notifications before doing the phone auth which I believe may be the cause of the error.
EDIT 2
I can confirm that on a fresh device with a fresh install of our app, if you disable Background Refresh then Firebase Phone Auth will not work. Once you enable it, it will work again.
The reason is that the SDK likely calls [[UIApplication sharedApplication] registerForRemoteNotifications] which is ignored by the system if a user manually disables the Background Refresh and Notifications settings.
Unfortunately there is no workaround until Firebase releases a new SDK which does not require APNs.
I am using Firebase to set up push notifications on iOS 10.
My app is receiving remote messages while in the foreground, but not in the background. Background messages are only received on opening the app.
Somehow all push notifications are received through applicationReceivedRemoteMessage:, Firebase's data message delegate, while in fact I never send a data payload.
I exactly implemented AppDelegate as mentioned in the tutorial on Firebase's website, I set the APNS tokens myself and the certificates are all in the right place. Also, my payload is sent with priority 'high' and content-available.
Anyone got an idea why iOS 10's native remote message handler (userNotificationCenter:willPresentNotification:withCompletionHandler:) is never called instead?
Thanks a lot! (Have been debugging this for two days straight now...)
I just ran into this same problem.
I resolved it by adding the following text to sender:
"notification":{"body":""}}
Don't set the Firebase delegate and just handle it in the old method
didReceiveRemoteNotification
look into firebase method swizzling
The FCM SDK performs method swizzling in two key areas: mapping your
APNs token to the FCM registration token and capturing analytics data
during downstream message callback handling. Developers who prefer not
to use swizzling can disable it by adding the flag
FirebaseAppDelegateProxyEnabled in the app’s Info.plist file and
setting it to NO (boolean value). Relevant areas of the guides provide
code examples, both with and without method swizzling enabled.