Google Sign In Button error when trying to login - swift

I have followed all the steps of the Firebase instructions for adding a Google Sign In Button. I have two problems when I open the app I have to wait a couple of minutes before pressing the Google button otherwise it gives me an error, after the first sign in if I try more still gives me the error.
(I added all the pods, all the app delegate function requested, the url in the target section of the app, the google.key-value list, and tried all possible solutions from other similar questions)
The errors I get are
Optional(Error Domain=com.google.GIDSignIn Code=-5 "The user canceled the sign-in flow." UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.})
Please if someone could help, cause I tried all stack overflow and google possibilities, and still not working.
Here is snippet of my code:
import Firebase
import GoogleSignIn
class ViewController: UIViewController {
var googleButton : GIDSignInButton!
viewDidLoad(){
self.googleButton = GIDSignInButton()
self.googleButton.style = .iconOnly
self.googleButton.frame = CGRect(x: 120, y: 300, width: 75, height: 75)
self.googleButton.addTarget(self, action: #selector(configureGoogleButton), for: .allTouchEvents)
self.view.addSubview(self.googleButton)
}
function configureGoogleButton(){
//get client Id
guard let clientID = FirebaseApp.app()?.options.clientID else {return}
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.signIn(with: config, presenting: self)
{ user,error in
guard error == nil else {
print("The app is not working")
print(error)
return }
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)
self.googleCredential = credential
print(user?.profile?.email)
print(user?.profile?.name)
}
Here is part of the app delegate:
import Firebase
import UIKit
import GoogleSignIn
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
func application(
_ app: UIApplication,
open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
var handled: Bool
handled = GIDSignIn.sharedInstance.handle(url)
if handled {
return true
}
// Handle other custom URL types.
// If not handled by this app, return false.
return false
}
}

Related

400 Invalid_request You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy for keeping apps secure

I am getting this error when I am trying to register with Google in my IOS app. I have got the REVERSED-CLIEND_ID which looks like something like this: com.googleusercontent.apps..... So far I can open the google window and I get the 400 error.
AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ApplicationDelegate.shared.application(application,didFinishLaunchingWithOptions: launchOptions)
GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
if error != nil || user == nil {
// Show the app's signed-out state.
} else {
// Show the app's signed-in state.
}
}
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
ApplicationDelegate.shared.application(
app,
open: url,
sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplication.OpenURLOptionsKey.annotation]
)
var handled: Bool
handled = GIDSignIn.sharedInstance.handle(url)
if handled {
return true
}
// Handle other custom URL types.
// If not handled by this app, return false.
return false
}
}
ViewController:
let signInConfig = GIDConfiguration.init(clientID: "REVERSED_URL_THING")
#IBAction func googleRegister(_ sender: UIButton) {
GIDSignIn.sharedInstance.signIn(
with: signInConfig,
presenting: self
) { user, error in
guard error == nil else { return }
guard let user = user else { return }
// Your user is signed in!
}
}
If anyone came across the same issue, in Xcode's URL Types add iOS URL scheme and do not use reversed url like it was said in many tutorials. Use the CLIEND ID which Google provides:
let signInConfig = GIDConfiguration.init(clientID: "CLIENT ID ")

SwiftUI swizzling disabled by default, phone auth not working

I am building a screen with phone number login. I checked over and over again and the project is newly created, however, I am getting this log:
7.2.0 - [Firebase/Auth][I-AUT000015] The UIApplicationDelegate must handle remote notification for phone number authentication to work.
If app delegate swizzling is disabled, remote notifications received by UIApplicationDelegate need to be forwarded to FIRAuth's canHandleNotificaton: method.
I did read in the documentation about swizzling and I don't know why it seems to be disabled, I did not disabled it. I have added GoogleServices-Info.plist into the app, I added in firebase panel the app apn auth key.
My entry point in the app looks like this:
#main
struct partidulverdeApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
MainView()
.onOpenURL { url in
Auth.auth().canHandle(url.absoluteURL)
}
}
}
}
My URL Types property has an entry with the RESERVED_CLIENT_ID
I am very desperate about this problem. Any idea is highly appreciated.
Edit1:
I did read the documentation and tried to handle notification with swizzling disabled, but I get the same error:
class AppDelegate: NSObject, UIApplicationDelegate {
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, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("Your code here")
return true
}
}
#main
struct partidulverdeApp: App {
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
MainView()
.onOpenURL { url in
Auth.auth().canHandle(url.absoluteURL)
}
}
}
}
Here's how to implement Phone Number Auth using the new SwiftUI 2 life cycle:
Create a Firebase project and set up PhoneNumber Auth
Add your iOS app to the Firebase project, download and add GoogleService-Info.plist to your project
In Xcode, select the application target and enable the following capabilities:
Push notifications
Background modes > Remote notifications
Create and register an APNS authentication key on the Apple developer portal
Upload the key to Firebase (under Project Settings > Cloud messaging in the Firebase Console)
Add the Firebase project's reversed client ID to your app's URL schemes
In your Info.plist, set FirebaseAppDelegateProxyEnabled to NO
Implement the AppDelegate as follows:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
print("SwiftUI_2_Lifecycle_PhoneNumber_AuthApp application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.")
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("\(#function)")
Auth.auth().setAPNSToken(deviceToken, type: .sandbox)
}
func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("\(#function)")
if Auth.auth().canHandleNotification(notification) {
completionHandler(.noData)
return
}
}
func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
print("\(#function)")
if Auth.auth().canHandle(url) {
return true
}
return false
}
}
#main
struct SwiftUI_2_Lifecycle_PhoneNumber_AuthApp: App {
#UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
print("Received URL: \(url)")
Auth.auth().canHandle(url) // <- just for information purposes
}
}
}
}
For further reading, I suggest these two articles I wrote:
Firebase and the new SwiftUI 2 Application Life Cycle
The Ultimate Guide to the SwiftUI 2 Application Life Cycle

Swift 4 Firebase online status update

I build chat app. I have field in each user table which allow to check if user Online. I use just database reference to get isOnline status and update it when pull to refresh. I seen that apps update online status automatically when user open or fold app. How i can do that? Do i need any listener or any framework can help me upgrade my code)) Something like ReactiveCocoa/ReactiveSwift...
P.S sorry for cyrillic text on field isOnline) it means Online/Offline
When application start you can update user online in AppDelegate
Update user online
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
// status parameter indicate user Online
if Auth.auth().currentUser != nil {
OnlineOfflineService.online(for: (Auth.auth().currentUser?.uid)!, status: true){ (success) in
print("User ==>", success)
}
}
return true
}
Update user Offline
func applicationWillTerminate(_ application: UIApplication) {
if Auth.auth().currentUser != nil {
OnlineOfflineService.online(for: (Auth.auth().currentUser?.uid)!, status: false){ (success) in
print("User ==>", success)
}
}
}
Firebase online and offline update service
import UIKit
import FirebaseDatabase
struct OnlineOfflineService {
static func online(for uid: String, status: Bool, success: #escaping (Bool) -> Void) {
//True == Online, False == Offline
let onlinesRef = Database.database().reference().child(uid).child("isOnline")
onlinesRef.setValue(status) {(error, _ ) in
if let error = error {
assertionFailure(error.localizedDescription)
success(false)
}
success(true)
}
}
}
Also you need to take care about user network connection. If user network connection off you just call OnlineOfflineService with parameters
I know this is an older question, but if you want to set the online/offline value to false when user closes app, use .onDisconnectSetValue():
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
setInactivityObservers()
return true
}
func setInactivityObservers() {
guard let user = Auth.auth().currentUser else { return }
// get user branch of database
let ref = Database.database().reference()
let usersRef = ref.child("Users")
let userRef = usersRef.child(user.uid)
// set "isOnline" branch to true when app launches
userRef.child("isOnline").setValue(true)
// set value to false when user terminates app
userRef.child("isOnline").onDisconnectSetValue(false)
}
First
Database.database().isPersistenceEnabled = true
Then manage the "presence"
let presenceRef = Database.database().reference(withPath: "disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnectSetValue("I disconnected!")
Then when the user is disconnected
presenceRef.onDisconnectRemoveValue { error, reference in
if let error = error {
print("Could not establish onDisconnect event: \(error)")
}
}
And Finally, to detect the status
let connectedRef = Database.database().reference(withPath: ".info/connected")
connectedRef.observe(.value, with: { snapshot in
if snapshot.value as? Bool ?? false {
print("Connected")
} else {
print("Not connected")
}
})
Is it ok now ?

Use of unresolved identifier 'url'

I'm completely new to API's, and am following this tutorial on appcoda
https://www.appcoda.com/dropbox-api-tutorial/
It's been going very smoothly, but I've run into a problem, and given that I'm a novice, I don't have the first clue with how to fix it.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let appKey = "n00nzv68gtxk6c9" // Set your own app key value here.
let appSecret = "itumv0icksr7yj6" // Set your own app secret value here.
let dropboxSession = DBSession(appKey: appKey, appSecret: appSecret, root: kDBRootDropbox)
DBSession.setShared(dropboxSession)
return true
if DBSession.sharedSession().handleOpenURL(url) {
if DBSession.shared().isLinked() {
NotificationCenter.defaultCenter.postNotificationName("didLinkToDropboxAccountNotification", object: nil)
return true
}
}
return false
}
The problem is in the line
if DBSession.sharedSession().handleOpenURL(url) {
where I get the error
Use of unresolved identifier 'url'
What do I need to do?
Per the tutorial, you need to use the correct delegate method within AppDelegate.swift
// handle custom application schemes
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
if DBSession.sharedSession().handleOpenURL(url) {
print("Url defined as \( url)")
}
}

Facebook login issue in Swift and iOS9

I have been trying to create a Tinder clone app. Right now I have to login to my Facebook account, grab my profile and show my display picture.
I have imported the latest FBSDK, confirgured my plist (Plist screenshot) correctly and used the graphRequest function to pull my profile picture but I keep getting the following error.
-canOpenURL: failed for URL: "fbauth2:/" - error: "(null)"
I have cleaned my build, restarted my simulator, restarted my machine and completely commented out my parse code.
I have uncommented all my parse code (which I am deploying through Heroku) so as not to simplify the code.
I have Googled the problem and searched stack overflow and github for over 2 weeks and have yet to find a solution.
I have read comments about how this problem is a red herring due to Facebooks SDK integration with iOS 9.
I want to know what I am doing wrong. I am new to coding and need some help. All I want to achieve right now is to login to my Facebook account (which I can do), authorise my app (which I can also do) and see my profile picture in the UiImageView (which I can NOT do). This way I can keep building the app along with my course.
/**
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
//current project 02-04-16
import UIKit
import Parse
import Bolts
import FBSDKCoreKit
import FBSDKLoginKit
import ParseFacebookUtilsV4
// If you want to use any of the UI components, uncomment this line
// import ParseUI
// deleted parseFacebookUtils and added ParseFacebookUtilsV4 so that PFFacebookUtils.intializeFacebookWithLaunchOptions would work. Replace parseFacebookUtils if needed to go back to old code (19-04-16).
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
//--------------------------------------
// MARK: - UIApplicationDelegate
//--------------------------------------
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Enable storing and querying data from Local Datastore.
// Remove this line if you don't want to use Local Datastore features or want to use cachePolicy.
// Parse.enableLocalDatastore()
//
// let parseConfiguration = ParseClientConfiguration(block: { (ParseMutableClientConfiguration) -> Void in
//
// ParseMutableClientConfiguration.applicationId = "tinder9121hughglass1234"
// ParseMutableClientConfiguration.clientKey = "sam123456hibabina"
// ParseMutableClientConfiguration.server = "https://tinder-sam2.herokuapp.com//parse"
PFFacebookUtils.initializeFacebookWithApplicationLaunchOptions(launchOptions)
// Uncomment these lines if you want to enable Parse
// PFUser.enableAutomaticUser()
//
//
// PFUser.logOut()
// let defaultACL = PFACL();
//this is the current project 23-03-16
// PFUser.enableAutomaticUser()
// Parse.setApplicationId("tinder9121hughglass1234", clientKey: "sam123456hibabina")
//this code has been // temporarily 05-04-16 ***
//
// let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
// fbLoginManager.logInWithReadPermissions(["public_profile"], handler: { (result, error) in
//
//
// })
//
// PFUser.enableAutomaticUser()
//
//
// })
// edited again here!
// let PFObject = PFUser.currentUser()
//
// PFUser.enableAutomaticUser()
//
// let acl = PFACL()
// acl.publicReadAccess = true
// acl.publicWriteAccess = true
// PFObject?.ACL = acl
// let defaultACL = PFACL();
// If you would like all objects to be private by default, remove this line.
// defaultACL.publicReadAccess = true
// PFACL.setDefaultACL(defaultACL, withAccessForCurrentUser: true)
if application.applicationState != UIApplicationState.Background {
// Track an app open here if we launch with a push, unless
// "content_available" was used to trigger a background push (introduced in iOS 7).
// In that case, we skip tracking here to avoid double counting the app-open.
let preBackgroundPush = !application.respondsToSelector("backgroundRefreshStatus")
let oldPushHandlerOnly = !self.respondsToSelector("application:didReceiveRemoteNotification:fetchCompletionHandler:")
var noPushPayload = false;
if let options = launchOptions {
noPushPayload = options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil;
}
if (preBackgroundPush || oldPushHandlerOnly || noPushPayload) {
PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
}
}
//
// Swift 1.2
//
// if application.respondsToSelector("registerUserNotificationSettings:") {
// let userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound
// let settings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
// application.registerUserNotificationSettings(settings)
// application.registerForRemoteNotifications()
// } else {
// let types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Alert | UIRemoteNotificationType.Sound
// application.registerForRemoteNotificationTypes(types)
// }
//
// Swift 2.0
//
// if #available(iOS 8.0, *) {
// let types: UIUserNotificationType = [.Alert, .Badge, .Sound]
// let settings = UIUserNotificationSettings(forTypes: types, categories: nil)
// application.registerUserNotificationSettings(settings)
// application.registerForRemoteNotifications()
// } else {
// let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
// application.registerForRemoteNotificationTypes(types)
// }
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
//--------------------------------------
// MARK: Push Notifications
//--------------------------------------
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.saveInBackground()
PFPush.subscribeToChannelInBackground("") { (succeeded: Bool, error: NSError?) in
if succeeded {
print("ParseStarterProject successfully subscribed to push notifications on the broadcast channel.\n");
} else {
print("ParseStarterProject failed to subscribe to push notifications on the broadcast channel with error = %#.\n", error)
}
}
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
if error.code == 3010 {
print("Push notifications are not supported in the iOS Simulator.\n")
} else {
print("application:didFailToRegisterForRemoteNotificationsWithError: %#\n", error)
}
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
}
///////////////////////////////////////////////////////////
// Uncomment this method if you want to use Push Notifications with Background App Refresh
///////////////////////////////////////////////////////////
// func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// if application.applicationState == UIApplicationState.Inactive {
// PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
// }
// }
//--------------------------------------
// MARK: Facebook SDK Integration
//--------------------------------------
///////////////////////////////////////////////////////////
// Uncomment this method if you are using Facebook
///////////////////////////////////////////////////////////
// func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
// return FBAppCall.handleOpenURL(url, sourceApplication:sourceApplication, session:PFFacebookUtils.session())
// }
func applicationDidBecomeActive(application: UIApplication) {
FBSDKAppEvents.activateApp()
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?,
annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
}
Try add this line into your Info.plist: <string>fbauth2</string>