Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google + login iOS App rejection from appstore using google sdk v3.x

After digging a lot I am here posting my problem. I am using google sign in latest sdk in my app and the app supports iOS 8+. I am using Xcode 7.2 currently. Recently my app got rejected with the very common reason which many users have experienced in the past:

FROM APPSTORE
We noticed that the user is taken to Safari to sign in or register for an account, which provides a poor user experience. Specifically, Google log in takes users to Safari to sign in.

Next Steps

10.6 Please revise your app to enable users to sign in or register an account in the app.

We recommend implementing the Safari View Controller API to display web content within your app. The Safari View Controller allows the display of a URL and inspection of the certificate from an embedded browser in an app so that customers can verify the webpage URL and SSL certificate to confirm they are entering their sign in credentials into a legitimate page.
END

I already know this rejection as apple has rejected lot of apps which are taking the Sign In flow out in the Safari browser. Here are some of the links for reference
https://code.google.com/p/google-plus-platform/issues/detail?id=900
https://github.com/Torsten2217/google-plus-platform/issues/900

and some more links you can easily find on Internet

On May 2015 Google released a new sdk with native web view. The complete process of integration is listed here http://www.appcoda.com/google-sign-in-how-to/.
It was working fine with iOS 8 and was presenting a controller too.

Now I was using the latest google sdk which I installed via CocoaPods https://developers.google.com/identity/sign-in/ios/start
The above link from google has a Try Sign-In for iOS sample which I tried. It is now opening a native SFSafariViewController in iOS 9 only but in iOS 8 the login flow is again going outside the app to Safari browser.

In the comments apple reviewer asked to use SafariViewController but the availability of the control is from iOS 9 and above. Here is the link https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller
How can I achieve this with latest google sdk in iOS 8?
The reviewer has neither mentioned the iOS version he/she was testing.

Now can anyone help me in sorting this out. How can I manage in iOS 8, the native present controller for Google Login page.

like image 652
Rajan Maheshwari Avatar asked Apr 14 '16 17:04

Rajan Maheshwari


1 Answers

Finally the problem is sorted out with latest Google+ Sign SDK and the app is also approved by Apple. I am posting a solution for both iOS 9 and iOS 8.
Use CocoaPods for integration.

pod 'Google/SignIn'

To start with login you have to do exactly the same steps mentioned in the Start Integrating Section here

Now in the Add Sign-In part, I want some custom button in my custom class of UIViewController to initiate the login process. In the developer link of Google, they are redirecting in AppDelegate only. So to avoid this I will not be using GIDSignInDelegate in my AppDelegate class

I will only be making changes in the following two methods of AppDelegate

//This is available for iOS 9 and above. So we have to use this method if we are integrating Google Sign In in iOS 9
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject])

//This is available prior iOS 9 and is available for iOS 8,7 etc. This is a deprecated method for iOS 9. You have to override this too if your app supports iOS 8 platform.
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool

So the definitions will be as follows:

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {

    if #available(iOS 9.0, *) {
        return GIDSignIn.sharedInstance().handleURL(url, sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as? String, annotation: options[UIApplicationOpenURLOptionsAnnotationKey] as? String)
    } else {
        // Fallback on earlier versions
    }
    return true
}

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {

    return GIDSignIn.sharedInstance().handleURL(url,sourceApplication: sourceApplication,annotation: annotation)
}

Now moving on to our Custom UIViewController class i.e LoginViewController, implement the GIDSignInDelegate and GIDSignInUIDelegate

class LoginViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate {

}

There is a custom UIButton for Google + login whose definition is

@IBAction func googleLoginButtonPressed(sender: AnyObject) {

    // Initialize sign-in
    var configureError: NSError?
    GGLContext.sharedInstance().configureWithError(&configureError)

    //assert(configureError == nil, "Error configuring Google services: \(configureError)")
    if configureError != nil {
     //Handle your error
    }else {
        GIDSignIn.sharedInstance().shouldFetchBasicProfile = true
        GIDSignIn.sharedInstance().clientID = kClientId
        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().uiDelegate = self

        //This did the trick for iOS 8 and the controller is presented now in iOS 8
        //We have to make allowsSignInWithBrowser false also. If we dont write this line and only write the 2nd line, then iOS 8 will not present a webview and again will take your flow outside the app in safari. So we have to write both the lines, Line 1 and Line 2
        GIDSignIn.sharedInstance().allowsSignInWithBrowser = false  //Line 1
        GIDSignIn.sharedInstance().allowsSignInWithWebView = true   //Line 2

        GIDSignIn.sharedInstance().signIn()
    }

}

Now the implementation of delegate methods for Google + Sign In

func signIn(signIn: GIDSignIn!, dismissViewController viewController: UIViewController!) {
    self.dismissViewControllerAnimated(true) { () -> Void in       
    }
}

func signIn(signIn: GIDSignIn!, presentViewController viewController: UIViewController!) {
    self.presentViewController(viewController, animated: true) { () -> Void in
    }
}

func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!, withError error: NSError!) {
    if (error == nil) {

        // Perform any operations on signed in user here.
        let userId = user.userID                  // For client-side use only!
        let idToken = user.authentication.idToken // Safe to send to the server
        let fullName = user.profile.name
        let givenName = user.profile.givenName
        let familyName = user.profile.familyName
        let email = user.profile.email
    } else {
        print("\(error.localizedDescription)")
    }
}

func signIn(signIn: GIDSignIn!, didDisconnectWithUser user: GIDGoogleUser!, withError error: NSError!) {
      //Perform if user gets disconnected
}

Now this will work in both iOS 8 and 9 without moving your app outside to Safari for Login purpose in Google +.

like image 126
Rajan Maheshwari Avatar answered Oct 06 '22 01:10

Rajan Maheshwari