Common Issues With Google+ Sign-In On iOS

With everyone's hearts all a-flutter over the prettiness of iOS 7 from WWDC, I thought it would be a nice moment to summarise some potholes I've seen people trip over while implementing Google+ Sign-In on iOS. While overall it's pretty straightforward, there are some things that can make life a little tricky. However, for reference I've also put up a simple gist of a sign-in implementation that includes an AppDelegate and a ViewController with the sign-in button on.

In this case though, we'll take a look at some problems that might bite you during development, and some that might hit later on.

Forgetting the resource bundle

When you include the Google+ iOS SDK, you need three files: GoogleOpenSource.framework, GooglePlus.framework, and GooglePlus.bundle. If you forget the frameworks you're likely to get a big obvious compile error about not being able to find the classes you want to include, but the bundle can be a bit more subtle. It contains the translations for the supplied GPPSignInButton, and it includes the images which that button uses. If you don't include it everything will still compile - you'll just get an invisible button (which looks like the button hasn't loaded at all), as it can't find the images.

Forgetting -ObjC linker flag

The GoogleOpenSource.framework contains a number of files from the Google Toolbox for Mac, a very helpful collection of open source utility classes and libraries that are used extensively in Google libraries and apps. Several of these are implemented as categories, adding functionality often to foundation classes. Because of the vagaries of Objective-C linking, these category references don't necessarily cause their defining classes to be pulled in from the static libs that come with the SDK. This means that you get odd "unrecognized selector" errors around methods like gtm_httpArgumentsString.

The solution to this is to add the -ObjC flag to the "Other Linker Flags" in the project's Build Settings. This instructs the compiler to pull in the code for these categories, and everything can proceed smoothly.

One important point here is that the flag is case-sensitive: missing the capital O or C is pretty easy to do, and will result in the same kind of error.

Not setting up a callback URL - or having it slightly wrong

A number of operations in the SDK involve the user coming in from another application. These include sign-in, where the user will be redirected out to the Google+ app or browser to sign in, then directed back to the application; sharing where the user is taken out to the browser and then back; and deeplinking, where the user is sent to the application from the Google+ app. To do these things, the app needs to have defined a custom URL scheme, and that custom URL scheme needs to be registered in the API console. That custom URL scheme is based on the bundle ID of the application.

While failing to do this is fairly obvious (e.g. the user is left in Safari, Chrome or the Google+ app after the operation rather than being redirected back to your app), one issue that often trips people up is getting the bundle ID slightly wrong! It's very easy to have setup a client ID with a small typo in the bundle ID, that then doesn't match what is generated from the application itself. Always check that field closely if you have any errors around redirecting. Of course, once you redirect the call needs to go somewhere, leading to...

Not registering a openURL handler

Even if the bundle ID is right, it's really important to make sure that the GPPUrlHandler is defined to handle the call. This is a new-ish helper that manages routing openURL calls to GPPSignIn, GPPShare and GPPDeeplink depending on the type of the call. It returns a BOOL so you can easily check it if you have other openURL handlers.

Not using trySilentAuthentication

If you've ever wondered how to avoid having the user sign-in each time the app opens, trySilentAuthentication is your friend. If the user has already signed-in, the SDK stores a keychain entry for that, and (most of the time) calling trySilentAuthentication will fire the finishedWithAuth:error: call on the sign-in delegate in short-order.

The trySilentAuthentication call will return a BOOL to indicate whether it has a stored credential. If it does, you'll probably sign-in succesfully, but there is always the chance that the user has disconnected your application from the Google+ side, leading on to...

Not handling errors based on disconnect

Offering disconnect in an app is really important for Google+ Sign In. It's also pretty easy from the app itself: [[GPPSignIn sharedInstance] disconnect]. The tricky thing tends to be managing disconnects that have occurred in other applications, or (even more challenging) from the Google+ apps management page directly.

As of version 1.3.0 of the SDK, if there is no access token a new one will be automatically fetched, and finishedWithAuth:error: will be called with an error if the refresh fails. However, there is an edge case where the app is disconnected, but is still open on the user's iOS device. In this case, the access token will appear valid, but calls will fail.

To guard against this problem, you can check the error.code coming back in the completion block from API calls - 401 indicates that the call was unauthorised and will usually mean a token has been revoked - it's generally a sensible move to reset the user to a signed out state by calling [[GPPSignIn sharedInstance] signOut].

Not adding files for other APIs

It's common to want to use multiple Google APIs in one project, but just because the Google+ SDK contains a GoogleOpenSource framework, that doesn't mean it includes every class used by every other API. It's important to make sure to add any dependencies those APIs may have - for example if using the Google Drive SDK, GTMHTTPUploadFetcher is needed in order to upload files to Drive.

Forgetting to add a consent screen icon

You may have noticed that in the latest Google+ iOS app there is a place to actually manage your connected apps, and that the apps have an icon displayed there:

Just like on the consent screen, this icon is taken from the Branding Settings under your project in the API console. If you haven't uploaded an image there, you'll get some rather dull grey squares.

Hopefully you can avoid these issues in your own apps! If anything isn't clear check out the gist and the official documentation, and don't hesitate to ask a question in the Google+ Developers Community, or on the Stack Overflow tag!

Popular posts from this blog

Common problems with Google+ Sign-In on Android

Client-Server Authentication with ID tokens

Are you using approval_prompt=force?