"Invalid Token" when trying to authenticate phone number using firebase - ios

This is my code:
import FirebaseAuth
class AuthPhoneNum {
static func getPhoneNum(phoneNumber: String) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber) { (verificationID, error) in
if let error = error {
print(error)
return
}
UserDefaults.standard.set(verificationID, forKey: "authVerificationID")
}
}
static func verify(verificationCode: String?) {
guard let verificationID = UserDefaults.standard.string(forKey: "authVerificationID") else { return }
if verificationCode != nil {
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationID,
verificationCode: verificationCode!)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print(error)
return
}
}
} else {
print("No verification code")
}
}
}
This is what the console prints out:
Error Domain=FIRAuthErrorDomain Code=17048 "Invalid token."
UserInfo={NSLocalizedDescription=Invalid token.,
error_name=INVALID_APP_CREDENTIAL}
What am I doing wrong? Thanks

I was also experiencing this problem. Checked the following:
Correct bundle Id
Correct Google-Info.plist
Correct aps-environment value
Correct APNS token type when calling auth.setAPNStoken (.unknown for auto detect)
Nothing helped until in Firebase app settings I uploaded the APNS authentication key (p8) instead of certificates - I used those certificates before for push notifications only and everything was working fine but for phone number notifications something went wrong.

It is most likely that you need to upload an .p8 Key file
(I have an Enterprise account but same thing for developer)
In Apple Developer Account:
All Keys
Create New Key (+)
Type in Global name for all of your apps
Checkbox next to Apple Push Notifications service (APNs)
Download your p8 file
Upload to firebase dashboard

First regenerates APNS key and upload in firebase for cloud messaging
1) Import Firebase and FirebaseAuth
import Firebase
import FirebaseAuth
2) In didFinishLaunchingWithOptions Configure firebase.
FirebaseApp.configure()
3) Write these two func in AppDelegate.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let firebaseAuth = Auth.auth()
firebaseAuth.setAPNSToken(deviceToken, type: AuthAPNSTokenType.prod)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let firebaseAuth = Auth.auth()
if (firebaseAuth.canHandleNotification(userInfo)){
print(userInfo)
return
}
}
Very Important note : uthAPNSTokenType set correctly for [sandbox / production] or set for common .unknown
In my case it was the apns token type that was wrong:
Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.prod)
should have been:
Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.sandbox)

In my case, the problem was an incorrect bundle id in the iOS app, in the firebase project settings (Project settings -> General -> Your apps).
I hope this helps anyone overlooking the same detail.

same problem questions have been before on SO. so would like to tell you setup all pre-require step before run code.
Pre-Require Steps:
Register bundle id on Developer account and enable notifications for
bundle id.
Register same bundle id on firebase console setting page and create
app, download Google-Info.plist file, make sure name should be same.
Upload Push certificates on firebase console for sandbox as well as
development.
follow this below link for code implementation.
setup code for Firebase Auth

Make sure that it is APNs that you are selected under Key Services. The number of APNs certificates per developer account is limited to 2. So if you already had 2 certificates before, there is a chance that you are created the certificate by checking DeviceCheck instead of APNs.

For any one else who double checked the above and still have issues, don't forget to add your team ID and App Id in your ios config file.
And, don't forget to download it again, and replace your old one with the updated one.

If you have tried adding the APNs key (p8) in your Firebase console and also checked for the Correct bundle Id and Correct Google-Info.plist.
And still the issue persists
Do check if you have "Push Notifications" enabled and "Remote notifications" selected in "Signing and capabilities" in Xcode->Runner but are not actually using firebase messaging
Then care to uncheck "Remote notifications" from "Signing and capabilities" and remove "Push Notifications" in Xcode->Runner.
In my case this was the issue

I faced same problem when I want send OTP and get notifications, I created APN key on apple developer console then added it to firebase after that everything got well:

If you did everything right as per the documentation. Try one thing.
Paste this line in AppDelegate.m under,
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[FIRAuth auth] setAPNSToken:deviceToken type:FIRAuthAPNSTokenTypeProd];

Related

Some registrations don't seem to be registered in Notification Hub

I'm trying to integrate my Android and iOS native apps with Notification Hub.
For example, on iOS, as soon as I receive the deviceToken and if my user is already authenticated, I register directly with NotificationHub:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
log.debug("Received device token \(deviceToken.hexEncodedString()). Saving device token to user defaults.", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken")
let defaults = UserDefaults.standard
defaults.set(deviceToken, forKey: UserNotificationDeviceTokenKey)
defaults.synchronize()
if let authenticatedUser = Session.shared.authenticatedUser {
log.debug("Trying to register device token \(deviceToken.hexEncodedString()) to user \(authenticatedUser.id) on notification hub with hub name \(String(describing: hubName)) and connection string \(String(describing: connectionString)). Notification hub null? \(notificationHub == nil)")
self.notificationHub?.registerNative(withDeviceToken: deviceToken, tags: Set<String>([authenticatedUser.id]), completion: { error in
if (error != nil) {
log.error("Error registering for notifications: \(error.debugDescription)", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken");
} else {
log.debug("Successfully registered device token \(deviceToken.hexEncodedString()) for user with ID \(authenticatedUser.id) and email \(authenticatedUser.emailAddress)", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken")
}
})
}
}
And whatever happens, I start by saving the device token to the user defaults so that when a user does log in, he can retrieve the deviceToken from user defaults and call the same registerNative method to create a registration associating this deviceToken with a tag that is the user's identifier:
func userDidSignIn(user: User) {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let deviceToken = UserDefaults.standard.data(forKey: UserNotificationDeviceTokenKey){
log.debug("Trying to register device token \(deviceToken.hexEncodedString()) to user \(user.id) on notification hub with hub name \(String(describing: appDelegate.hubName)) and connection string \(String(describing: appDelegate.connectionString)). Notification hub null? \(appDelegate.notificationHub == nil)")
appDelegate.notificationHub?.registerNative(withDeviceToken: deviceToken, tags: Set<String>([user.id]), completion: { error in
if (error != nil) {
log.error("Error registering for notifications: \(error.debugDescription)");
} else {
log.debug("Successfully registered device token \(deviceToken.hexEncodedString()) for user with ID \(user.id) (\(user.emailAddress)) who just logged in", context: "HTRootViewController.userDidSignIn")
}
})
} else {
log.warning("No device token found in settings.", "HTRootViewController.userDidSignIn")
}
}
I have all my logs remotely sent to Bugfender, which lets me check the logs for all the devices using this app installed in TestFlight, so I can see that all the registerNative's are successful:
Trying to register device token
0fea9a4d99ec37dc4f3ac252c35fa4e1617004fd14740973d80a7dfdaeacc857 to
user 77bfb1c6-b05a-440b-a7a0-71ae5a91bbb2 on notification hub with hub
name Optional("[my notification hub name]") and connection string
Optional("[my notification hub connection string]").
Notification hub null? false
Successfully registered device
token 0fea9a4d99ec37dc4f3ac252c35fa4e1617004fd14740973d80a7dfdaeacc857
for user with ID 77bfb1c6-b05a-440b-a7a0-71ae5a91bbb2
([my user's email]) who just logged in
But then, when I load the list of all the registrations using this .NET C# code:
public async Task<List<RegistrationDescription>> GetRegistrations()
{
var hub = NotificationHubClient.CreateClientFromConnectionString([my notification hub connection string], [my notification hub name]);
var result = await hub.GetAllRegistrationsAsync(1000);
return result.ToList();
}
I can see that some registrations are there, but others are nowhere to be found, even though they succeeded according to my mobile logs.
Does anyone know what else could be going on? What else can I check? Why else would registrations not be saved even though the call to registerNative seems to succeed?
EDIT: As a matter of fact, and after checking more precisely what is happening, the registration first appears in the list of registrations returned by Notification Hub, but as soon as we try to send a notification, it's as if Notification Hub could not reach the corresponding device token and deleted the registration altogether. Is there a way to see the logs of Notification Hub to see what is going on and why it decides to delete this registration?
I figured it out. It turns out it was working on my device because I ran the beta in debug mode, so it was getting its device token from the Sandbox APS environment, which matched the Sandbox endpoint configured in Notification Hub, but other users were using the Production APS environment configured in the archive build, so they got device tokens for a different environment and notification hub correctly identified as incorrect device tokens. Once we switched the Notification Hub to the production APNS endpoint, all the TestFlight users were able to receive notifications because their registrations stayed in Notification Hub. Now that does mean that my debug builds trying to use that environments won't receive notifications, but that's OK, that's why we have a different environment and Notification Hub for development purposes. So if anyone sees something similar, don't forget to double check your Notification Hub configuration matches the type of build your users are using, and don't forget that TestFlight builds are now production-type builds, same as App Store builds.

React native FCM iOS push notification not delivered

first of all environment is React native, I try to setup push notification in iOS following instruction from rnfirebase package here what step i do and I do testing on Real iPhone Device
create key
then add to firebase
add Google-service.plist and add setup following from firebase doc
and acivate capabillity
then I install pod package
run app got token
use token send on cloud messaging console
notification not delivered I didn't know what wrong because message also send from FCM and what happens on APNS where I get an error just confused
thank for advance
and also try by connecting directly with pusher
and also not received again
then try to use Onesignal with same certificate with Firebase is work even on the test message
The token you are using in Pusher doesn't look right. My tokens for remote notifications look like this.
I was just testing silent pushes, but the token would look similar for regular alerts. Here is the code I use to grab the token. My guess is that you are pushing a bad token up to FCM.
fileprivate func convertHexDataToString(_ data: Data) -> String {
var string: String = ""
for i in 0..<data.count {
string += String(format: "%02.2hhx", data[i] as CVarArg)
}
return string
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenString = convertHexDataToString(deviceToken)
#if DEBUG
print("APN sandbox token: '\(tokenString)'")
Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
#else
print("APN prod token: '\(tokenString)'")
Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
#endif
}

Testing passwordless auth in Firebase test lab for iOS

I am trying to figure out how to perform e2e test via firebase test lab for iOS that allow to check passwordless authentication flow, which essentially should do following
Enters email within my app
Firebase sends auth link to such email
Somehow I need to be logged into such email somewhere in firebases test device, I assume either in mail app, or gmail?
I need to know when new email arrives and open it
Once I opened an email I need to click on auth link
This should bring me back into the app and authenticate
My biggest issue at the moment is figuring out steps that happen outside my app i.e. how can I prepare for this test and log in under my email address (is it better to log into gmail in safari for example or somehow add this acc to apples mail app?).
Testing email
In my experience, testing your own code to see if an email was sent is not straightforward beyond checking if the method call you expect to send the email has happened.
Add on top of that using Firebase, which does not expose its underlying email send code, and that looks like a challenge to me.
In terms of testing, I suggest you assert that your method calls to send email happened or that the relevant code path was reached. In Firebase web, this looks like:
firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
.then(function() {
// The link was successfully sent. Inform the user.
// Save the email locally so you don't need to ask the user for it again
// if they open the link on the same device.
window.localStorage.setItem('emailForSignIn', email);
// TODO save email to something accessible in your iOS tests
// TODO In your tests, confirm that email was saved after it was sent
})
.catch(function(error) {
// Some error occurred, you can inspect the code: error.code
});
See: https://firebase.google.com/docs/auth/web/email-link-auth#send_an_authentication_link_to_the_users_email_address
Another option:
You could setup a test user with an email address on a mail server that you manage, and check for incoming mail for that test user with your own custom mail reading code.
I would use Firebase Admin tools for this: https://firebase.google.com/docs/auth/admin/manage-users#create_a_user
I think you should first take a look at firebase docs for iOS on how to create dynamic links that you can use for email auth.
https://firebase.google.com/docs/auth/ios/email-link-auth
https://firebase.google.com/docs/auth/ios/passing-state-in-email-actions#configuring_firebase_dynamic_links
After you're done with those two check out the following code:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
// [END old_delegate]
if handlePasswordlessSignIn(withURL: url) {
return true
}
}
func handlePasswordlessSignIn(withURL url: URL) -> Bool {
let link = url.absoluteString
// [START is_signin_link]
if Auth.auth().isSignIn(withEmailLink: link) {
// [END is_signin_link]
UserDefaults.standard.set(link, forKey: "Link")
(window?.rootViewController as? UINavigationController)?.popToRootViewController(animated: false)
window?.rootViewController?.children[0].performSegue(withIdentifier: "passwordless", sender: nil)
return true
}
return false
}
This is just an example on how you can handle the deep link in your app after the user taps the link. The delegate method
func application(_ application: UIApplication, open url: URL,
sourceApplication: String?, annotation: Any) -> Bool
in AppDelegate is used for all deep links into an app. You could set up for example your own scheme that your app conforms to. And you can send url type links with your custom scheme into your app from the browser for example.
To do this just Open Xcode, go to Project Settings -> Info, and add inside ‘The URL Types” section a new URL scheme. Add something of the sort of com.myApp in order for it to be as unizue as possible. Then you can just type into a browser com.myApp://main and handle that in the appDelegate.
Edit: It says so in their docs that you can present a prompt inside the app for the user to input the email. Where the user opens his email from isn't really your concern as long as your dynamic link is set up properly.

Not Getting CloudKit Push Notifications

I had push notifications from CloudKit working and I'm afraid I've done something to break them. If anyone can see something I don't, please help.
When the app launches, I call setupSubscriptions(), which has this code:
let predicate = NSPredicate(value: true)
let subscriptionID = "public-new-changes-deleted"
let subscription = CKQuerySubscription(recordType: recordType, predicate: predicate, subscriptionID: subscriptionID, options: [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion])
let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo
publicDB.save(subscription) { subscription, error in
if error != nil {
print("subscription was set up")
}
The setup message does fire. I've also tried making the notificationInfo CKQuerySubscription.NotificationInfo, but there's no discernible difference whether it's that or CKSubscription.
In my app delegate:
application.registerForRemoteNotifications()
I do get a message from application(_ application:, didRegisterForRemoteNotificationsWithDeviceToken:) that the application has registered for notifications.
Then I have:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("application did receive remote notification")
}
Next I got to my CloudKit Dashboard and create, modify, or delete a record but nothing happens. I'd expect a message from didReceiveRemoteNotification. but nothing. This was working earlier but I can't think of what I changed to break it.
I can create records there and query for them in the app, so I'm sure it's able to see them, but I can't get a push when they're altered.
Other stuff:
In my target's Capabilities tab:
Background Fetch and Remote Notifications are both checked under Background Modes.
iCloud is on and it's using the correct container -- I can do fetches just fine from CloudKit using the same recordType and publicDB CKDatabase object.
Push Notifications are turned on and my entitlements file has a flag for "APS Environment" with a value of development.
On my Apple Developer account page, under the App ID, iCloud and Push Notifications both have green lights for both "Development" and "Distribution."
I can see in the CloudKit dashboard that the subscription types are created once the app's been run.
I'm testing on a device, not in the simulator.
I've tried:
Changing whether I create the subscription before or after I register for notifications.
Adding a message body, alert sound, and shouldBadge, and requesting notifications using UNUserNotificationCenter, and making the App Delegate a UNUserNotificationCenterDelegate. I get the prompt when I first run the app but the notifications don't arrive.
Splitting the subscriptions up into one for .firesOnRecordCreation and one for update and delete.
Adding the subscriptions using a CKModifySubscriptionsOperation instead of the database's save method.
Please let me know if you have any ideas. Thank you.

com.facebook.sdk.core error 8

This is more informative than anything. I couldn't for the life of me find anything on error code 8 when trying to access the login prompt (aka safari) when debugging my ios app. After I hit the log into facebook button in my app it would attempt to open safari then dump me back to the login page to my app. The error was being caused by the permissions array. I had the the permission "public_profile" spelled "public profile" which was throwing an error obviously. So make sure your permission are type corrected if you get the com.facebook.sdk.core error 8.
Hope that helps someone.
Make sure your permissions are typed correctly
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if error == nil {
println("login complete")
self.performSegueWithIdentifier("showLogin", sender: self)
}else{
println(error.localizedDescription)
//com.facebook.sdk.core error 8.
}
}
In my case this error was caused by improper bundle id set in facebook settings of the app itself. Facebook "bundle id" is case sensitive, in my Info.plist I had uppercase product name, but in fb settings - lowercase.
In my case, I was using a Facebook account that hadn't yet been added to any of the Facebook app's admins/developers/testers roles.
In my case, after spending several hours of debugging I found that I was using the API,
func application(application: UIApplication,
openURL url: NSURL, options: [String: AnyObject]) -> Bool {
if #available(iOS 9.0, *) {
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: options)
} else {
// Fallback on earlier versions
}
return true
}
which is deprecated for iOS 9.So, I used:
func application(application: UIApplication,
openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
return true
}
Which worked for me. Hope this saves time of someone.
MAN!!! In my case it was the "bio" in the parameter that was causing this error. Facebook has changed the "bio" key to "about". So anyone using "bio" in parameters should change it to "about"
Pheww!!!
In my case It was wrong version. Instead of version: "v2.7", I used version: "2.7"
In my case it was because I listed name twice in the fields array. Assume that would apply to any field requested twice.
I had the same problem. It was because I didn't implement facebook login feature. After adding that, I logged in and my problem got solved.
In my case, I was playing with the Facebook Ads API and I tried to get a field but the name was wrong.
I had insights{date_start,date_end}, instead of insights{date_start, date_stop}.
More info here.
Hope it helps anyone.
In my case, I tried to get Facebook Id without logging into Facebook. Make sure you're logged into Facebook.
let accessToken = FBSDKAccessToken.current()
if accessToken != nil {
self.getCurrentUserFbId()
print("LoggedIn")
} else {
print("Not loggedIn")
self.loginIntoFacebook()
}
Hope this will helpful for anyone.
When it happened to me, I found that Facebook's access token was expired. Someone decided to store access token in UserDefaults and reuse it later. Of course all tokens more than ~2 months old were expired.
In my case it was because of GraphRequest.
The error response is
"com.facebook.sdk:FBSDKErrorDeveloperMessageKey" = "Syntax error
\"Expected end of string instead of \"%\".\" at character 5:
email%2Cname%2Cgender%2Cpicture";
"com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey" = 0;
"com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCode" = 2500;
"com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey" = 400;
"com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey" = {
body = {
error = {
code = 2500;
"fbtrace_id" = AFEUYbcYP39;
message = "Syntax error \"Expected end of string instead of \"%\".\" at character 5: email%2Cname%2Cgender%2Cpicture";
type = OAuthException;
};
};
code = 400;
};
The issue about that is https://github.com/facebook/facebook-swift-sdk/issues/309
In my case was because of birthday,friendlists . removing them started to work.
For me just had to go facebook developer under platform and activate deep linking
In our case we were seeing this issue while trying to log in with some test account (but not all). We were not following Facebook's recommended practice:
Before you test each use case below, make sure you remove your app from your test user's Facebook account using app settings.
After we did it for the failing test accounts, we were able to log in.

Resources