Search code examples
iosgoogle-app-enginegoogle-cloud-endpointsgoogle-signin

How do I make authenticated calls to Google Cloud Endpoints from an iOS client using Google Sign-in for iOS?


I've implemented these instructions in my iOS app:

https://developers.google.com/identity/sign-in/ios/sign-in

And these ones in my Google Cloud Endpoints API:

https://cloud.google.com/appengine/docs/java/endpoints/consume_ios

except that of course I don't do the bit with the GTMOAuth2ViewControllerTouch.

The two do not marry up. The endpoints service in the iOS app needs an authorizer set on it, one that implements GTMFetcherAuthorizationProtocol. Where do I get this authorizer from the Google Sign-in callbacks?

This callback on the AppDelegate gets passed a GIDGoogleUser instance, which has a GIDAuthentication instance, which has an accessToken field (String). That's what I want to pass to App Engine:

func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!, withError error: NSError!) {
    log.debug("Access token: \(user.authentication.accessToken)")
    // TODO: What do I do with this now?
}

Here's where the generated service needs the token. In my case the API is not very well named as just "Api", so the generated sources are GTLServiceApi, GTLQueryApi, etc.

private func executeQuery(query: GTLQueryApi, completionBlock: (object: AnyObject!, error: NSError!) -> Void) -> Void {
    let service = GTLServiceApi()
    service.retryEnabled = true

    // Whatever we set here should implement GTMFetcherAuthorizationProtocol. Where do we get one of those from the Google Sign-in SDK?
    // service.authorizer = TODO

    service.executeQuery(query, completionHandler: {(ticket, object, error) -> Void in
        completionBlock(object: object, error: error)
    })
}

Solution

  • (I've been tracking this issue for months, and finally figured it out...)

    Once you are signed in, the GIDGoogleUser object returned has the authorizer attached as: user.authentication.fetcherAuthorizer

    This object can be used as the authorizer for the endpoints service and everything seems to work!

    That said, if you want to make your app more closely follow the approach laid out at https://cloud.google.com/appengine/docs/java/endpoints/consume_ios, you might instead use GTMAppAuth, which seems to be the more similarly designed replacement for the GTMOAuth2 approach in that example.