application:openUrl doesn't get called when using GIDSignIn

443 Views Asked by At

Here's how my AppDelegate looks like:

class AppDelegate: UIResponder, UIApplicationDelegate,GIDSignInDelegate {
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
    if let error = error {
        // ...
        return
    }

    guard let authentication = user.authentication else { return }
    let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
                                                   accessToken: authentication.accessToken)
}

//For ios 9.0 or above
func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any])
    -> Bool {

        return GIDSignIn.sharedInstance().handle(url,
                                                 sourceApplication:options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
                                                 annotation: [:])
}

func application(_ application: UIApplication, open url: URL, sourceApplication:

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

I added a GIDSignIn button in my storyboard and in my ViewController I assign the UIDelegate to it:

class LoginRegisterViewController: UIViewController,UITextFieldDelegate,GIDSignInUIDelegate {
  override func viewDidLoad() {
    super.viewDidLoad()

    bindUIDelegate()
    GIDSignIn.sharedInstance().uiDelegate = self

            //registerForKeyboardNotifications()
}
.......

When I clicked the GIDSignInButton, it pop up a Google Signin page and then I entered my credential and hit login. Then it directs me back to my app.

I insert a break point in the AppDeletgate.sign() method, I can see it does get hit after it redirects back to the app. But I DON'T see my application:openurl method get called even when I put a break point in it.

So my question is: when does that method get hit? It's said that at the end of authentication process from here: https://firebase.google.com/docs/auth/ios/google-signin. But I'm not seeing it gets hit and seems like the AppDeletgate.sign() still works fine even though I remove the application:openurl method.

1

There are 1 best solutions below

0
codecitrus On

This was confusing me as well, so did some digging. The general steps involved are the following: (1) App starts the browser (2) User goes through auth flow on browser (3) Browser redirects to you app's URL scheme (4) IOS detects scheme and instead of opening the URL in browser, it knows to open your app and pass the url (containing the auth tokens) to it.

I guess previously, the result of step (4) was IOS opening your app with the application(...) entry point, passing in the url containing the token. You would then manually call GIDSignIn.handle(url). Looking at the code, we see that handle(url) calls resumeExternalUserAgentFlowWithUrl. This latter method is part of the AppAuth library which is what Google Sign In uses behind the scenes.

Currently, however, the AppAuth library does things differently. Instead of opening a generic browser session, it uses the ASWebAuthenticationSession API provided by IOS to open Safari. With this approach, instead of opening your app with application(...), the ASWebAuthenticationSession will call a completionHandler it was created with.

Looking at the AppAuth library code. We see that it is this completionHandler that now calls resumeExternalUserAgentFlow

TLDR: Instead of opening generic browser session, google sign in now uses ASWebAuthenticationSession which opens Safari to complete your auth flow. When the auth flow completes with a redirect to your app url, instead of IOS opening your app with application(url), the ASWebAuthenticationSession will directly invoke a callback method. Google Sign In implements this callback method for you to handle the resulting url.

Note: ASWebAuthenticationSession has some security benefits. Namely, w. the old approach, someone else could register to handle your own url scheme with their app. This means their app would get the token. However, ASWebAuthenticationSession guarantees the callback on "your app" will be called even if someone else has registered their app w. same url scheme. Pretty cool stuff.