Google+ Sign-In: Page Level Configuration

On Monday the Google+ Javascript SDK team announced the release of a number of enhancements to the sign-in SDK on the web. These are all things that have either been directly requested by developers, or were created in response to something that developers have asked for, but I wanted to go into a bit more depth on one of the more subtle, but also very useful, changes.

The feature is the combination of the page level configuration and the dynamic sign in callback. This simplify managing configuration for a page, makes managing sign-in state easier, and generally provide a much better feel for the user.

Page Level Config

The biggest change is moving configuration information from either HTML data- attributes or Javascript options to meta data on the page itself. This means that you won’t run into a problem of having one button configured with scopes A and B, but another with just A (which can lead to confusing situations), or miss out some app activity types. The configuration is supplied as meta tags with names constructed from google-signin- + the option, e.g. clientid.

As you can see this allows you to define the callback as well, so you really don’t need to pass any options to a sign-in button:

<div class=“g-signin”></div>

Dynamic Sign-In Callback

This is the one that really improves the experience for me though. One of the general problems developers faced was how to trigger an immediate mode check. If you display the sign-in button, then it can be there for a while before the check has completed, which looks a bit odd to a returning user. The normal method was to hide the sign-in button off screen until the check had been completed. With this change, the callback will fire on initial page load.

On top of that, it also tracks the sign-in state of the user. Try visiting the example page in an incognito window, sign-in, and then in another tab sign out of Google. You'll see an error immediate_failed_user_logged_out. The reverse would happen if you signed-in using the same browser instance, and had previously granted access. Very cool!

This means we can drive behaviour directly from the callback, which actually makes the code simpler. Here we are just checking the state and displaying the appropriate buttons. We don’t need to worry too much about whether the user is signed-out, not logged in to Google, automatically signed-in or manually signed in. Just as an example, we’ll tweak the message depending on whether they consented or were seamlessly signed-in.

The important thing to note in the callback is that we’re not triggering this by creating the button - we only call gapi.render when we have a confirmed signed-out state, so our flow is much more cleanly encapsulated.

Read More

Using Google Services To Grow User Retention

Brian Balfour recently wrote an interesting post about the measures startups use at different stages of growth. In the early days of building a startup its really important to have a regular stream of users trying our the application or service, and for a decent number of users to come back and continue using it.

Having decent retention makes it a lot easier to experiment. A group of real users to give feedback and spread word about your product is a worthwhile goal. Getting users to try an application is a pretty difficult thing, but the worst result is to have those users bounce having only scratched the surface of the product. If you get a user to the point of signing-in to your application, then its worth rolling out the red carpet to give them the best chance of having a good experience, and to give them opportunities to come back. One of the best things about using social sign-in like Google+ Sign-In is the access to services which you can use to enhance that out of the box experience. This post has a few tools that might help you do that.

Tailor the experience to the user

All too often, the user signs in and gets presented with a generic “trending” stream, "popular with other users", or worst of all, the blank screen! Particularly in the early days of an application you won’t have a lot of graph information, so users are unlikely to know other people on the service to help give them a good starting experience. That doesn't mean you can provide a compelling out of the box view of your application though, it just means you have to do a little more work to build your understanding of the user.

Using profile data

One of the first places to look is the users profile. If you have a signed-in user, calling the plus.people.get method with the user ID me will return the basic profile information. As well as the user's name, profile picture, and very coarse information like gender, it can contain many more hints that let you tailor your experience.

1. Language.

The users language seems like a simple thing, but if you have content that matches its a good idea to expose it. This can also be a helpful analytics tracking value - if you discover that you have a particularly high session time with users who speak a certain language or from a certain region, that can be an area worth investigating.

"language": "en_GB”

2. Places Lived

While not always set, this could give you some useful hints towards interest - if someone has set it, they are likely to be interested in information related to the area. This is just text, but if you need to turn it into a location for a GIS query of some kind then the Geocoding API from the Google Maps team can help you out.

"placesLived": [
{
"value": "Brentford, UK",
"primary": true
}
],

3. Organisations.

This field contains organisations that the user has worked for, or educational establishments the user has attended. Not every user will have this filled in, but you can see the type and name of each organisation if they have. Skillpages make great use of this to help pre-fill your work experience.

"organizations": [
{
"name": "University of Sussex",
"type": "school",
"primary": false
},
{
"name": "Google",
"title": "Developer Advocate",
"type": "work",
"startDate": "2012",
"primary": true
}
],

4. URLs.

This is one of my favourite sources of data, for two reasons. Firstly, it often allows you to link profiles - mine contains links to my profiles on Twitter and Github for example, which can be helpful for disambiguating. Secondly, this can be a strong interest indicator - if you see the user uses Github, for example, they’re probably technical.

"urls": [
{
"value": "http://twitter.com/ianbarber",
"label": "ianbarber"
},
{
"value": "http://github.com/ianbarber",
"label": "Github"
},
{
"value": "http://phpir.com",
"label": "PHP/ir"
},
],

You can also pick up some interesting data for personalisation based on who the user follows. Its easy to pick up a collection of popular pages, for example from somewhere like CircleCount’s World Google+ page rankings . This can be associated with primary topics in your system - even if its a manual process, it shouldn’t be more than a few hundred associations. Then, when you check who the user has in their circles, you can infer a topic interest if any of those should match.

Calling plus.people.list with user ID me and collection visible will return a list of circles (or the ones the user has shared with your application at any rate). You can even order by best, which will use Google’s affinity metrics to rank the profiles in importance for the user. The first page I followed in the best ordering that was also in the top 100 is The Economist, which probably says something about my taste.

{
"kind": "plus#person",
"etag": "\"QR7ccvNi-CeX9lFTHRm3szTVkpo/uqkY5m1P_OedARGohHeKOJMYgGU\"",
"objectType": "page",
"id": "100470681032489535736",
"displayName": "The Economist .",
"url": "https://plus.google.com/+TheEconomist",
"image": {
"url": "https://lh6..."
}
},

Using other APIs

Its not just about data available from Google+ API calls either. In my previous post I outlined how you could get Freebase topics from a user’s YouTube watch history or liked videos - this gives you some key themes to use to retrieve relevant content from your own app.

This kind of thing is easy to see as a fit for a content based app, like a music service or something inherently social, but look for opportunities in your own application space. If you’re building an accountancy app, why not ask for access to Google Drive and look for files in common formats you might be able to automatically process, for example.

Build in ways to bring your users back.

Once you provided a good out of the box experience, you want to build in hooks that will encourage your users to come back to your app and explore more deeply. Wherever you can, build this into the normal flow of your application experience.

If you have any sort of timed event, you could use the Google Calendar API in order to create an event with calendar.events.insert. This requires requesting an extra scope when implementing sign-in, but if your app has time-based functionality (for example for a second screen app when a certain TV show is on), this can be a way of being useful to the user, and simultaneously reminding them of your app. Flixster allows you to invite your friends to see a movie at a certain time using an interactive post - if they accept, all are added to a Google Calendar invite. This is useful, and naturally reminds users about Flixster just around when they’re going to see a new movie - which is precisely when they're most likely to rate & review.

You can also use direct notifications. Google+ Sign-In can gives you access to retrieve the user’s email address. You can then contact them directly - but particularly when starting out only play that card at the right time! Apps only have one or two chances with a user before they’re going to get judged as spam. Its vital to ensure that the email content is valuable to the user, timely in its delivery - so it feels motivated as a notification worthy event, and easy to consume.

Email can be made a lot more powerful by taking advantage of features like Gmail’s actions to allow the user to immediately do something with the notification. These can be even for authenticated actions, by passing one time tokens in the email itself.

If building on top of a mobile platform, you also have the options of adding push notifications. Firing user notifications has the same risks as email - if they're not useful you'll be facing a quick uninstall. Because notifications can be more intrusive, try to ensure they respect:

  1. The user - make sure its personalised to them!
  2. The user's timezone - don't push when they're asleep (ideally push when you've seen them use the app in the past).
  3. The user's location - make sure you're not pushing them something which they couldn't use in their wrong country.

Share the process with your users

One of the best things you can do, particularly in the early days, is to start a conversation with your users. When you’re experimenting you’re hoping to cause reactions, and you need to be able to easily here what your users are saying. A Google+ community is a great way to do that, and if you’re building an Android application you can actually use a community as a method for giving users access to beta test your application.

Having participated in a couple of these beta communities I can say confidently that problems that would have caused negative Play store reviews are picked up all the time - and instead of the result being an unhappy user and am uninstall, the result is a dedicated fan who feels like they’re participated in the process.

Read More

Extracting Topic Data From YouTube Activity

YouTube is an amazing resource for creating and discovering videos, but it is valuable for people building non-video experiences as well. Looking at YouTube usage is a great way of finding out what a user is into, and can help provide information to allow a more tailored out of the box experience. It's really easy to request access to YouTube alongside Google+ Sign-In, and then use the YouTube API to retrieve the user's watch history or their likes.

YouTube offers several scopes for allowing access to different facets of the functionality, but in this case we will be using the readonly scope. This means the user only consents for the application to view their activity on YouTube, and doesn't grant it the ability to upload videos or subscribe them to channels. In an Android setup, we can request the scope with our call to PlusClient.Builder. Because the YouTube API is not part of Google Play services, we will also need to create a GoogleAccountCredential from the Google Java client library to use when making YouTube API calls.

When the user signs in, we need to set the chosen account on the GoogleAccountCredential object. In my test app I immediately kicked off the async task to retrieve the playlist as well, but you may want to do that later or maybe on a server.

We're aiming to retrieve a list of interests, which is done by retrieving the list of videos the user was watched, or has liked, and extracting some topic indicator from them. Liked is a stronger signal, but not every user will have liked any videos, so you may want to implement both. To actually do this there are four stages:

  1. Retrieve the user's channel details, to the get their playlist IDs.
  2. Retrieve the videos in the user's Likes or WatchHistory playlist
  3. Retrieve the video details of each video on the list
  4. Extract the Freebase topic ID, or the category of each video

The final point is where you actually extract the topic information. Sometimes there is a good match between category and your needs - for example if you are looking for music videos, then filtering by category 10 (music) and saving the video titles is likely to give you a good set of keywords to plug into your own system. However, if you need more specific data, then you can take advantage of the fact that every video on YouTube has one or more Freebase topic MIDs associated with it. You can aggregate these topics, and retrieve details on them from the Freebase API.

Retrieving The Channel

Every user on YouTube has an implicit channel, and retrieving it is the first call we'll need to make. We call the channels API with mine parameter set to true to indicate we want the current user's channels. We also have to specify a part parameter to indicate which part of the response we're interested in - here we use contentDetails. A user may have more than one channel, but we're interested in the default channel, which should be first. From there we can get the playlist ID for the likes or watch history playlists.

Retrieve the playlist video IDs

Next we need to query the playlist. We may well get more videos back that we can retrieve in a single call, so there proper operation here is to loop over the pages of results until we have all of them.

If we just wanted a sampling of videos, we could avoid this looping and just make a single call.

Retrieving videos

While for many uses the play list actually gives us enough information, for retrieving the category or the topic IDs, we need to retrieve the videos themselves. The videos.list call can return all this information, and luckily enough can take a comma separated list of video IDs. In this example, I'm just taking the first 50 video IDs, but we could make several calls and retrieve all the IDs.

In the loop across videos.getItems we are extracting the topic IDs. We're also keeping a count in case we want to filter by only the most popular topics. Sometimes we will see that topicDetails contains two entries - relevantTopicIds can give us better topical matches, though usually more general, and with fewer entries. We could use that in preference, or add it in.

Rather than retrieving the topic details and doing further processing, we could alternatively filter by category here if we wished, as indicated in the comment in the code above. An example of retrieving videos in the music category from my recent likes returns the list in the screenshot below. Also note the YouTube consent line in the dialog, which makes it clear that the access is read only.

Retrieving topic information

We will now have a list of topic to count mappings we can use, a series of pairs like this:

m/07lb3 => 5
m/09xp_ => 3

There are a lot of ways of actually retrieving the topic information. In many cases the identifiers will be enough - if you can map your own data to Freebase topics then it will just require a look up. You can actually get the whole Freebase data in a data dump, though this is quite large! An alternative is to try and find Freebase entities for parts of your database by using the Freebase search API. This allows finding entities based on natural language queries, so could be good for looking up known entities and storing MIDs

If we don't have a pre-existing mapping, we can make a call to the Freebase API to get topic details in JSON format with a simple GET request to a URL "https://www.googleapis.com/freebase/v1/topic" with the topic ID appended/m/09xp_. Working out how to fit this in with your own data can be quite tricky however. There are some guides to the Freebase structure in the developer documentation, where you can start to explore the ways that different topics and types are related, and how it might make sense to map to your own models.

The easiest way is often to look for notable types in the returned topic data. This should likely give you a general enough category to search again.

"/common/topic/notable_types": {
"valuetype": "object",
"values": [
{
"text": "Sport",
"lang": "en",
"id": "/sports/sport"
}
],
"count": 1.0
}

If you just want to play around with the YouTube data, the easiest way is to use the Google API explorer, where you can make all the calls and see the responses easily (the parameters hopefully should be clear enough from the code above).

Read More

User Sign-In Status In Javascript

I wanted to explain a small addition that has recently appeared in the Google Javascript API that a couple of people have asked me about. You may have notice that the argument to the sign-in callback (which I'll refer to as authResult) from the sign-in flow now contains an extra field: status. This simple object tells you a lot about how the user is accessing your page, and allows you to do some smoother and more reliable checks than before.

See if the user is signed in to your app

Rather than testing for the presence of the error or access_token properties, you can now test authResult.status.signed_in. This will be true for a user who has signed in to your app, false for a user that has not (or if we don't know, because they're not signed in to Google).

See if the user is signed in to Google

You could always use checkSessionState to see if the user had an active Google session, but now you don't have to make a separate call - that information is directly available whenever an immediate mode sign-in attempt is displayed (e.g. any time the button is in the DOM). Check the authResult.status.google_logged_in variable - true indicates an active Google session, false indicates that the user is logged out. Of course, if its false you'll only see this when signed_in is also false.

See how the user signed in

Several people built interesting methods to detect whether the user actively clicked the button, or were seamlessly signed in after an immediate check. Now there is no need! The status object includes a method variable: authResult.status.method. This will be set to null if the user hasn't signed in, "AUTO" if they were seamlessly signed in, and "PROMPT" if they saw the consent dialog or signed in after a gapi.auth.signOut.

Give it a go yourself, there is a small demo here that shows the status data after each callback.

The relevant bit of code is the callback, where it is just flipping the button state and displaying the status object:

One last warning - be a little careful when you serialise the authResult object. Because it can hold a reference to the consent screen window, there are cases where serialisation can trigger cross-origin violation in the console. If you need to send any information in the result to another party, do it explicitly. E.g. instead of sending authResult, just send authResult.id_token or whichever parts of the object you need.

Read More

Client-Server Authentication with ID tokens

These days there are few purely client-side applications - even traditionally unconnected software like casual games make use of servers and services to provide a better, richer experience - and importantly one that can follow the user across devices. We are in a world where we need to authenticate a user of many clients to a set of back-end services.

There are a few ways of doing that when using a identity provider, like Google, but in this post I want to talk about a specific method that makes use of ID tokens. This approach has been well covered by Tim Bray for Android, but with the release a couple of months ago of the iOS 1.4.0 SDK for Google+, it is now available across Android, iOS and the Web. This makes it a particularly powerful way of signing in a user, and asserting the identity of that user securely to your application servers.

Why ID Tokens

This whole architecture relies on a point of view which I suspect is still not particularly common amongst developers implementing authentication. We generally thought of social sign-in as a way of getting access to your identity and a bunch of realted service - so that you use social sign-in in the Android app, pass something to your server, and they could each take actions on the network: maybe the server writes to your social network, the client retrieves a profile picture (for example).

ID tokens are based on the idea that your server primarily focuses on providing services to your own clients. In this model, you authenticate your client, use that to identify the user to your server, and make any social API calls from the client alone. The server provides application specific calls, and if data sourced from the social network is needed, it can be passed via the clients. This, in general, leads to a pretty clean separation of concerns and a secure system. The ID token is pure identity, not authorisation - it doesn't grant the holder any ability to make API calls. It does contain information about them though, so it must only be sent over HTTPS.

This style is pretty similar to how we used to build systems with usernames and passwords, particularly on mobile. When the user starts an app, they were prompted to sign-in, and the username and password were sent to the server to authenticate them. After that, a session cookie was used form a connection between client and server. The client then would take advantage of services on the mobile application, such as location or the camera, and pass data as needed to the server. With ID tokens we take the same model, except instead of a username and password we pass a cryptographically signed assertion of who the user is, and as well as services like location and the camera we include calls to retrieve user information from Google APIs. In pictures, something like this:

ID tokens are part of the OpenID connect spec. If you receive an ID token you can verify who the user is, which app they are using, and who is asserting that. For example, if my server receives an ID token from a client, it can get the Google user ID, email address (if the user has granted permission on the email address to the app), the client ID the token was generated for, and who generated it. The validity of those statements can be checked cryptographically. The token is small enough to pass around with calls, and easy to retrieve and to verify.

Using an ID token

Here is what an ID token looks like:

eyJhbGciOiJSUzI1NiIsImtpZCI6ImFlOGU0NmMzN2UzOWMzY2ZiMTgxNWI2YjU4MmM2MTNiOTk0N2MxZTQifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXRfaGFzaCI6InFmdXFud3NXWWRzLXBzMW1oYkU5cXciLCJhenAiOiIzNjY2NjcxOTE3MzAtajRmdThwbnZjMmoxdHRrcmwxazdqdTVuNXBpbTN2ZXQuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiIzNjY2NjcxOTE3MzAtajRmdThwbnZjMmoxdHRrcmwxazdqdTVuNXBpbTN2ZXQuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTMzNDAwOTA5MTE5NTQ3NDE2OTYiLCJpYXQiOjEzODMxNDc0MjEsImV4cCI6MTM4MzE1MTMyMX0.Z2NVE5HQxsLXx_zRmG3bxgGPDUv76HffDYvhlU_OpgLDeeIxQnC7cAS2OkAUK-nkDci3rMTM035NeTQUKfHsUziOV_WGyDtuRq_KEBDev0ssr8EeTq0Wg-nYN8eo6nbfKYTtd4UnOMG-xYetyyPIN8SNy3G7P1Aw3CakhbD32I0

There are 3 dot separated sections, each base64 encoded. The second part is the payload, which looks like this. You can see the Google user ID (sub for subject), the creator of the token (iss for issuer), and the Google console client ID that the token was generated for (aud for audience).

 {
"iss": "accounts.google.com",
"at_hash": "qfuqnwsWYds-ps1mhbE9qw",
"aud": "132456789654.apps.googleusercontent.com",
"sub": "113340090911954741696",
"iat": 1383147421,
"exp": 1383151321
}

The first and third parts are part of the security mechanism. The third part is the signing hash - a digest of the first two parts created by Googles private keys. We can check that against Google's public certificates, which are rotated every few hours. The Google certificates are normally found on a standard URL, and are in a JSON structure with an identifier and the certificate in x509 format. The first part of the ID token identifies the algorithm used, and the identifier of the certificate used to generate the signature.

eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk1YTNjMjkwNTI4NGZlMTE3OGI1OTJjOTg4YWYyYjM5YjNjZTU4ZWQifQ{"alg":"RS256","kid":"95a3c2905284fe1178b592c988af2b39b3ce58ed"}

The signature part is verified by checking the signature against the public key. This is calculated over the first two parts of the ID token, in base64 encoded format. If this passes, we know that the signature was created across all the data in the ID token by the Google private key, so we can be sure of the source of the message.

Server Side

The normal setup for a system of this nature is to piggy-back the autentication information on the regular calls. This minimises round-trips, and helps to separate the different responsibilities in code. We will work on the basis that we will send the ID token to bootstrap a random session identifier, though it is also a valid design to simply pass the ID token along with every request - the cost being that is somewhat larger than a common session cookie, and takes more work to verify.

If the session cookie has expired or the client doesn't have one, the server indicates that it requires authentication. The client then repeats its request, with an ID token - in the example code below the token is sent as a GET parameter, but a more sensible design would probably pass it as an Authentication: Header. Similarly, the session is returned using the standard PHP session mechanism, but there are many methods for passing a token on calls.

Our server, in PHP, might look something like this:

Note the verifyIdToken function here. That is calling the Google PHP client library, and automatically manages retrieving the certificates from Google, checking the validity of the ID, and extracting the payload data. If you want to see all the details of the checks made, you can look directly at the client library function. Client libraries in other languages also include simple verification functions for ID tokens.

Retrieving in Javascript

The normal implementation across all platforms is to setup regular Google+ Sign-In, and in the "connected" callback retrieve the ID token and send to the server. Retrieving the ID token in Javascript is not more complicated than that. When the user signs-in the callback will fire with the normal access token, and so on. As part of that dictionary, the ID token is provided.

Retrieving on iOS

On iOS you must be using version 1.4.0 or above of the SDK. Once the user has signed-in you can retrieve the ID token at any time using the GPPSIgnIn sharedInstance.

While most of the time on the web we will be generating an ID token for the same client ID as on the server, with iOS and Android we will have separate client IDs. We can specify that we would like to generate a token for another client ID as long as it is in the same API console project as the client ID we are signed in to. You can see this with two different values in the azp (authorized party) and aud fields:

{
"iss":"accounts.google.com",
"cid":"911581857976-tbl0ni100qvqbjmrbkc2uo6jdure3k1h.apps.googleusercontent.com",
"azp":"911581857976-tbl0ni100qvqbjmrbkc2uo6jdure3k1h.apps.googleusercontent.com",
"email":"ian.example@example.com",
"id":"104824858261236811362",
"sub":"104824858261236811362",
"verified_email":"true",
"email_verified":"true",
"aud":"911581857976.apps.googleusercontent.com",
"iat":1384436584,
}

This example also includes the email address, as that scope had been requested as part of the sign in process. You may also note there are a few duplications of fields - this is due to supporting both the current and previous iteration of the OpenID connect standard.

Android

Tim Bray's article is again the definitive source, but in general retrieving an ID token when you have a signed-in user is really straightforward. The only complexity on Android is that you have to make the actual call in an AsyncTask as it may perform a network operation:

Again, we specify the client ID of the home server, for easier verification. For completeness we must include a number of exception handling cases which is reality will not trigger - the getToken method on GoogleAuthUtil is overloaded to return access tokens and codes as well as ID tokens, depending on the scope parameter passed.

Hopefully you can see that there is some use in verifying backend calls using ID tokens. The fact that it can be used across the three primary platforms with Google+ Sign-In makes it a great way to consider building your system if that is your sign-in mechanism. Because its sending a token to set up a session, its very compatible with other methods of authentication - conceptually its the same idea as sending a username and password when the user has no session, but more secure!

Be sure to always send ID tokens over HTTPS - though they can't be used maliciously in themselves, an attacker could use one to establish themselves a session with your app server if they could intercept it, so its important they aren't send in plain text.

Read More

Improving Sign-In Implementations

I've written before about common technical problems with Google+ Sign-In implementations, but there is whole other class of errors that I've seen in applications. These generally aren't technical mistakes per se, but more about best practice.

One the aims of the guidance on developers.google.com/+ is to promote a standard experience - users trust new applications because they behave in a way they expect. A good implementation does this, and makes all three parties involved happy: the app developer, the identity provider, and the user.

Bad consent screens

Common problems with consent are asking for more access or more scopes than are needed, and not adding a logo and clean name. For example, take this consent screen

Here the app name is generic, and not tied to where the user was signing in. The app is requesting full access to both my Drive account and my YouTube data, and there is duplication - it asks for basic information, and basic profile. Each of these can be resolved. We can add an icon and a better name via the developer console, so that the user can be confident they're granting access to the app they expect. The redundant profile information is due to requesting https://www.googleapis.com/auth/userinfo.profile as well as https://www.googleapis.com/auth/plus.login, so we can remove userinfo.profile without any negative - all of the profile data will be available from the plus.people.get API.

The excessive YouTube and Drive scopes can be scoped down to just what we need - perhaps requesting only "view" access with the https://www.googleapis.com/auth/youtube.readonly scope, or just access for appdata on Drive. It may also be that we don't really need that scope at all - there are at least a couple of high profile sites who request the ability to manage your contacts on sign-in simply because they cut and pasted the scopes from a demo, and don't actually use them!

Another common problem is requesting access to too many different kinds of app activity. Only request the ones your app is actually going to write, or likely to write in the near future.

Blocking seamless sign on

The Google+ Sign-In view of identity is that it is a service that an application requests access to, much like an app requests access to location in a browser or native app. The app shouldn’t have to badger the user to renew it when no further access is being asked for. Therefore if a user signs-in to an application using Google+ sign-in on one computer, then goes to use the app on another which has the same Google account, they should still be signed in.

This is accomplished in on the web through the fact that most users are signed in to Google somewhere, perhaps Gmail or YouTube for example. As long as they have an active cookie, we can use an iframe pointing to Google to check that same cookie, and then look up whether the user has approved a given site. This means I could go to a site for the very first time on a certain browser, and it could immediately know I previously granted access, and smoothly sign me in without having to click a button. On Android this same functionality is accomplished via the AccountManager, which will store the user's Google account and again make it available to be checked.

Not using this functionality means users have to choose to sign-in to your app again, even though they have previously consented. There are generally three reasons why people disable it:

1. Implementing using redirect based OAuth 2.0 rather than the Javascript and postmessage based version. Normally this is due to migrating from one of the older scopes, or using middleware. This is a very reasonable way to implement sign-in, but it is normally not massively difficult to migrate to the Javascript method: replace generation of the URL with outputting the sign-in Javascript, and instead of redirecting the user to a callback URL with a code in the query parameters, XHR the code to the server and redirect once a cookie has been established.

2. Intentionally disabling the sign-in callback on the web in order to allow users to simulate sign-out. If you want to let you users mark themselves as signed out, the best way now is to use gapi.auth.signOut.

3. Not checking for the sign-in state. This one happens particularly on Android, where app does not connect a PlusClient on startup. This means that while the user may have previously approved the app, they aren’t actually signed in until they visit a login activity. The same kind of problem does occur on the web.

On the web, try implementing the sign-in button as default hidden with CSS, and only make it visible if you get an immediate_failed callback (or wait till the user clicks on a login page). This will allow you to include it in each page, and check whether the user has previously consented without necessarily having to show them an UI.

On Android, implement the PlusClient in a base activity, or in a fragment that your activities include. Again, if you get the onConnected callback you know the user is signed in, but if you get onConnectionFailed you could just ignore it until the user visited a login activity.

In both cases, you don’t have to actually display a sign-in button everywhere, but you should test for signed-in state anywhere the user can enter your application.

Immediately asking for a password or other registration data

Passwords are kind of bad. People re-use them, they take work to store properly, and they need to be combined with other checks such as SMS for 2-factor authentication in order to be properly secure. However, it is a very reasonable desire not to have a third party be the only access method for a user's account. Instead of asking for a password right after a user signs in, why not generate a long, random password for them - then they can always use a Forgot Password flow if they want to access their account without using Google.

If you need other data, think about whether you absolutely need to prompt the user for it right after sign-in. Sometimes this is unavoidable, for example if you need to have an explicit age check, but in most cases the user can fill in the extra information as it becomes necessary. For example, if your app can filter results by location, and you want to know their home city but don't have the data via their profile, rather than asking up front for the information you could present an option letting the user know why: "Filter these results to your home town" or similar. Then when the user clicks, it would be natural and straightforward to ask for their home city.

Using the wrong branding

There are some branding guidelines that are worth taking a look at. In general, make sure that if your button doesn’t say “Sign in/Login/Connect With Google+” but “With Google”. It should still have the G+ icon though! The easiest thing to do is to use the buttons that are provided - this ensures that users who are familiar with sign-in will immediately recognise it, which hopefully will lead to a higher percentage of them signing in.

Not allowing users to disconnect

Disconnect is a distinct action from sign-out. Thinking back to that idea of identity as a service that the user grants access to, sign-out is temporarily not using the server, while disconnect is full revoking access. In fact, that is how it is implemented - calling the token revocation endpoint. What this does, from a users perspective, is signs them out everywhere, and marks the app as disconnected in the Google+ apps page, or the equivalent in the Google+ Android and iOS apps.

This is an important part of the trust in a system - the knowledge that the user can sever the link between their app account and Google+ profile, and not leave any access. Not that many people actually do disconnect, but the fact that it is there is important. It’s best to put a disconnect option in a settings page - somewhere discoverable, but not top-line visible (that should probably be for sign out, if implemented). Actually implementing requires two things: revoking access, and removing any data stored from the Google+ API. It doesn’t require deleting the account or anything similar.

If you had stored the placesLived data from a users’s Google+ profile, and they disconnected, it would be reasonable to pop up an editable form with that data. This could ask them to confirm they wanted you to have this data, and perhaps also allow them to set a password for continued access.

Actually disconnecting is generally very easy. Both Android and iOS have helper methods: revokeAccessAndDisconnect on Android and disconnect on iOS. For the web or server side its just a case of hitting the revocation endpoint with either a refresh or access token - both will revoke all access.

Adding disconnect, requesting extra data in context, fixing the branding or consent screen and enabling seamless sign-on are generally not large amounts of work, but doing the right thing can help users feel confident in the application, and more likely to use it. I would say that of the lot, allowing seamless sign-in will likely have the biggest visible impact on usage, but all of them should help the flow of registration.

Read More

Saving App Config To Google Drive

Once you get beyond the basics of adding Google+ Sign-In, and start looking at what is available across the Google platform there are some real gems to be found. One of these is a fantastic feature of Google Drive called appdata, which allows an application to store data in a user’s Drive account without worrying about the user fiddling with it. These is handy if you’re building something like a Javascript web app and need some storage, but don’t want to setup a server. Unlike localStorage or other browser based options it doesn’t rely on the user being on the same device, so it’s easy to allow users to access their data from wherever they are.

Most of the time this sort of feature seems a natural fit for mobile applications - as Drive is about manipulating files - but it’s just a straightforward to build it in to a web application. There’s a little form in the iframe below - you can sign in and save your data, and then if you sign in to another device you should have the same data available.

All this is doing is syncing the contents of the form to a state variable, and then reading and writing that state value to a file in the Drive appdata storage.

Setup

In order to gain access to the Drive app data folder, we need to request the appropriate scope, https://www.googleapis.com/auth/drive.appdata. We do this in addition to the regular plus.login scope for Google+ Sign-In in the scope parameter of the sign-in button.

This causes an extra consent line to appear. "View and manage its own configuration data in your Google Drive". Once the user accepts, in the onSignin callback we load the Google Drive Javascript API client and see if we have any existing state to retrieve.

Checking for the file

The app data is implemented in Drive as a special folder which only our app can write to. Because of that, we need to check whether our config file is available. The first step is to get a list of files in the folder, and look for one with the name of our config file.

Where we use the file.list method with a search query: 'appdata' in parents. This requests all files that are in the app data folder. appdata is a special string, much like "me" in Google+ sign-in, that refers to the folder of the currently connected application. We loop over the files and store the ID of the first file that matches our config filename. FILENAME in this case is just the constant we're using for the filename. In the sample it is 'appsettings.json'. The first time we connect there won't be a stored file. This will leave the file ID as null and use the local defaults in the state variable.

Saving the file

When the user hits submit for the first time, we need to actually create the file. This is done via a form post to a specific upload URL. We'll use the FormData object to actually create our multipart form post, consisting of a blob of JSON for the metadata, and the file data itself. The metadata defines our file name, the content type, and importantly that the file is in the appdata folder. The main file body in this case is also a JSON blob, so we just stringify both and add them to our form object.

There is a standard URL for these type of file uploads which we can POST our multipart form to. In future, once we have a file ID for our config file we can PUT to an address which includes the ID in order to update it.

Note that we include the OAuth 2.0 access token as a header on the post via the JQuery ajax call. We also disable local processing by JQuery so it passes through the form data properly.

Reading the file

Finally, we need to read the config file back when the user returns. To do this we make an API call with the file ID we saved from the list operation. This gives us to get a download URL that we can then fetch with an XHR. Because the file type is application/json, we can immediately treat that like an object and fill the form. One optimisation for a real system would be to store this file ID in local storage to save a network roundtrip for returning users on the same browser.

Again, we put the access token in the header while downloading. Once we have the file, we can just set our local state variable to the contents and again sync the form.

These same approaches can work from any client that can talk to the Drive APIs, which is almost anything. This means you could have the same config for native Android, iOS, and desktop apps as well as your web sign-in.

Read More

Triggering Google+ Widgets From Javascript

Recently I've answered a couple of questions from people that had a section of their site loaded dynamically with Javascript, and wanted to put a +1/Sign-In/Follow/etc button there. Google+ Sign-In along with all the Google widgets, can be marked up in HTML and rendered automatically when the plusone.js loader is included in the page. However, there are ways of controlling when that happens with explicit parsing, or triggering it directly with the render functions.

Lets say we have a page that contains a +1 button, a follow button and a post embed, though the same thing works with sign in, badges, and anything else. The most straightforward way to write that page is by using the markup based widgets, which all follow a similar form and look something like this.

Pretty much all the other widgets work the same way: a known class name which is scanned for when the async tag loads, and a series of parameters on the element specified as data- attributes to configure the behaviour of the widget. If we put this into a page, it loads and looks like this.

When plusone.js has loaded it automatically replaced the contents of the elements with the relevant widget. In some cases, such as interactive posts and sign-in, if there is already content in the tag it will be retained and a click handler added to trigger the appropriate behaviour instead. Of course, we might not want to do this right away, or we might want to bring in some element of a page dynamically. We can suppress the automatic parsing by using the parsetags config setting in the standard Google Javascript API config dictionary. This is generally best done at the top of the page, or in any case before plusone.js is loaded.

Now we can choose when to render the buttons by calling gapi.*.go(), where * is replaced with the type of widget we'd like to render. We can either call go() directly for each widget type, which will render all elements of that the of the page, or we can specify a container as the first argument to the go call. This is not the id of the element itself, but of a parent of that element. All widgets within the container will be rendered, but ones outside wont. In the example below, we'll attach the go calls to a button click:

In this snippet we have a function which is going to enable a button, and attach the click handler to it. When the button is clicked it will call go() for the plusone and follow widgets wherever they are, but only for the post widget within the element with ID postcontainer. Then, if our HTML looks like this:

The first post embed is within the postcontainer element, the second is not. When we hit the go button, only the first is rendered.

You might also have noticed that we only added the go button in a function. This is taking advantage of an extremely handy feature of the plusone.js loader. If you specify an ?onload=... parameter on the URL, it will call that function once the Google API client has loaded. You may also note I have client: prefixed to the filename. This means the loader comes with the client for API calls as well - we're not using that here, but I tend to, so this is the form of the async snippet I most commonly use.

We have a third option with rendering as well, and this is my preferred one. We can trigger the rendering directly with gapi.*.render, where again * is any of the widget types. The nice thing about this is that we can set all the properties in an options dictionary, so we can pass in closures and not be required to have global functions for things like callbacks. This also means that you can centralise your various bits of widget configuration more easily!

The first parameter to the render methods is either the ID of an element, or the element itself - not the container this time. The second argument is the options bundle, where we specify the information that was previously in data- attributes. This also means that instead of specifying data-callback="function_name" on the sign-in button, for example, we could actually inline the function, or refer to a function in another object. Notice that for the plusone and the follow buttons we're passing the element ID, but for the post we're passing the element itself. Either is valid!

In our example, we'll trigger the gapi.*.render calls in the startRender callback from the plusone.js loading, so we'll get the same effect as in the first post:

This time though, the actually HTML behind it is much simpler, as all of the attribute information is contained in the Javascript.

So, for any kind of content we can trigger rendering whenever we need, and by using the callback on the plusone.js loader we can be sure that all of the requisite Google Javascript code will be available.

Read More

Where should the sign-in button go?

One of the questions that you face as a developer when implementing Google+ Sign-In (or any login method) is how to present the options to the user. Having reviewed a pretty large number of apps with sign-in, I thought it might be helpful to break down the four main approaches for displaying the buttons that I've seen, and some thoughts on the costs and benefits of them.

A couple of points before we get into that: It's worth remembering that the best situation is when the user does not have to take any action at all. That's the idea behind cross platform single sign on and over-the-air installs. It's also why it is worth taking the time to make sure users stay signed-in after an app upgrade or releasing a new version of a website.

Secondly, unless there are solid reasons not to, sign-in should always be paired with sign-up. Particularly on mobile devices this can be a missed opportunity where users are expected register on the web first. That said, in this post I want to focus less on the whole flow, and more on how and where you present the sign-in option initially.

1. The Roadblock

In a roadblock the sign-in screen is presented up front to the user, and the only way that they can continue to use the app is to authenticate. There are some benefits to it - from a development point of view it means no time has to be spent considering anonymous users, and from the business point of view all of the benefits of a seamless experience and the ability to connect a users' actions across platforms are compelling. That said, there is a significant cost in doing this: it forces the user to immediately decide whether the app is worth signing in to, and the likely result of them not being sure is to uninstall the app or close the window. It is like someone demanding your ID as soon as you step through a door - sometimes its the right choice, but it never feels friendly.

The two examples above are Telly (on Android) and Flixster (on the web). In both cases, the applications could offer experiences for signed-out users, but have made the decision to force their users to sign-in before accessing.

There are some valid reasons for doing this. Some applications really don't make any sense without authentication - such as a banking app. In some cases the value of or for a signed-in user is so much higher that it is worth losing users who won't sign in. An app like the document scanner Doo has some value for anonymous users, but without connecting it to a cloud backend to save documents to it is a little precarious. Sometimes the roadblock is the right choice purely from the perspective of saving development time - but in that case the decision is definitely worth revisiting as the app matures.

The other downside of this technique is that it is very difficult to effectively convey why a user should sign-in in. One of the reasons this approach is more prevalent on mobile is that the user has already decided to download the app, and so has slightly more of an impression of what it might do for them. On the web, a roadblock is generally the first thing you see.

Nick, Roman and Adam rightly came down hard on this approach in a recent Android Design In Action. If you are considering it for your own application it's worth also looking at some of the other options. Be explicit about what you, and the user, are getting out of the exchange.

2. Roadblock with escape road

The more common technique for the web is to present sign-in like a roadblock, but allow deeper exploration via an escape route. This can recapture some of what would have been bounced traffic, and allow users to explore further while still heavily promoting the signed-in experience. Deezer are a good standard example for this on the web. They present sign-in as the primary action on the page, but allowing users to go deeper into the site via the search button. In case you can't access Deezer (sorry USA!), Soundcloud have a similar approach, though they make the exit routes more prominent. The choice of how much prevalence to give various elements is going to depend on the relative value of anonymous and authenticated users. In general there's a fairly granular sliding scale between the full roadblock and the convenience sign-in setup as described below, trading some percentage of lost views for some percentage of increased sign ins.

On mobile this technique is slightly less common, particular on Android where it is possible to request access to some kind of stable identifier simply by requesting the GET_ACCOUNTS permission on app install. The skippable roadblock is more common for social sign-in though, with Shazam's gorgeous new Android app being a prime example. Here again the social sign-in is presented as the primary action, but the user is given the option of avoiding it.

3. Convenience Sign-In

Sometimes sign-in is beneficial to the app, but not enough that you want it to get in the way of the user's experience. In that case, putting sign-in where it is visible but not intrusive can be a nice compromise. For example, many websites have a login or signup button in the top navigation, and users expect to find that feature there. We can see this on The Fancy, where the sign-in is prominent but certainly not getting in the way of the shiny things in the content. On mobile there isn't as much of a convention to follow, but 9gag provide a decent example by placing the sign-in option at the top of their stream where users will see it, but aren't pressured to sign-in. In this way sign-in is offered as a convenience.

Occasionally this option is included primarily for existing users, rather than to convert new ones. In this case it is accompanied by other, more direct techniques for presenting the sign-in option (mainly option 4 below). If it is the sole driver of sign-ins it usually indicates that the value of sign-in to users is low. Managing a user database and sign-in options requires effort, and if there isn't value for the user in registering then it is best either to not spend the effort on having a user sign-in at all, or to focus it on their areas where there is value. A common place to find this kind of problem is on magazine or newspaper sites, particularly smaller ones, where the main sign-in value is managing subscriptions but the site or app spends effort spreading the functionality across the entire product.

4. Contextual

The final method is to present the sign-in only at the time the user takes an action that clearly requires it. This is one of the most effective methods for converting viewers to users. They have already taken an action, and are presumably seeing some value from the application.

Picsart do this beautifully. The app allows you to take and modify photos right away. When it comes to posting them up for others to see them you are then prompted for the sign-in. To the user, the request is motivated by the action they took, so there's not a lot of explanation needed for why they should sign-in.

Just as with the roadblock, this can be accompanied by a skip option if the sign in is merely optional. For example, many eCommerce sites allow a user to create an account or sign-in at checkout, but also allow manually entering the order details without creating an account. In that case, a smart option may be to allow simpler account creation afterwards, once they have already entered all their details.

Where this technique can fall down is if there are small core of active users, but a larger base of mainly passive users. While offering more light-weight endorsements can encourage the passive users to interact more (e.g. +1 an item), it also provides much less incentive to sign-in: if I've presented with a dialog when I press the endorse button, I might just hit back. In this case either increasing the value to passive users or more prominently promoting the sign-in option may be a way to capture a higher percentage of the user base.

What to use?

The core questions to keep in mind when choosing how to present sign-in to users are:

  • What benefit does the sign-in give the user?
  • How can I best communicate this to my user?
  • How much do I value a user being signed-in vs being anonymous?

The answers may well vary per-platform, but the best apps will always have a strong benefit for both the user and the app of being signed in, and be able to clearly and quickly demonstrate that.

Read More

Google+ Android Client & Server Sign-In

NOTE: This blog post is pretty old! Take a look at a much better way of getting an authorization token or check out the official Google Sign In documentation for a more up to date (and easier!) choice.

Google+ Sign-In is a really easy way to authenticate and identify a user and build interesting experiences on Android. Some apps needs more than just an authenticated Android client though - they also need to make Google API calls from their server, perhaps even when the client is offline. Enabling both to access the APIs at the same time is slightly tricky, but in this post I'm going to try and break down what is required, and how you can do this in a robust and reliable fashion. Note that life is much easier if you just need either the client or the server to have API access, or just need to identify the user to a server. This approach is solely for the case where you make Google API calls on the Android client, and also Google API calls from the server.

Our model is that we have an application which needs to have authorisation to call some Google API, and a server which also needs authorisation, and continues to need access when the user isn't there. To achieve this the server stores a refresh token in some kind of database, which it can look up by the Google user ID. It also creates a session between the client and server, which is then used to make application (non-Google) API calls. Our goal is to have every user have a signed-in client, a refresh token on the server, and a session between them. When signing in on Android, we can choose to retrieve a code and send it to the server, but we have to be careful to avoid showing the user 2 consent screens, or exchanging the code for a refresh token when we already have one.

There are quite a few moving parts involved with various callbacks, as so much of the process is asynchronous. The best way I've found to think about this process is based on the scenarios of the users, which is how we'll look at the implementation. In each case, we progress through gathering additional information with a series of PlusClient connections and server calls until we arrive at the state where both client and server are signed in and have a shared session.

We'll go through 3 scenarios: new users, who have never signed in to your service, existing users who are returning to your application, and users who have logged out. Then, we can tie them all together with a bit of error handling. We'll start out with a basic Android activity as setup for Google+ Sign-In, with some state variables we will use to track the flow:

New Users

A user who is accessing the app/service for the first time will have no stored refresh token with the server, and so will certainly need the code. We start with setting up our PlusClient as normal, and triggering the connect in our onStart. In this case we'll get a call to onConnectionFailed, with a connection result which we can store for later.

Our onConnectionFailed just stores the connection result for the time being.

We can kick off the connect in the onStart method as normal, but we don't want to do anything right away, as the user hasn't chosen to sign in yet. Therefore, the magic actually happens in our onClick listener for the sign in button. In the normal flow we'd resolve the stored ConnectionResult now, but we want to retrieve a code instead so. We need to establish which user the wants to sign in with, so we can use the AccountPicker from Google Play Services:

This returns to our onActivityResult. Now we know which account the user wants to sign in with, we can retrieve the code and send it to our server.

Don't worry, we'll cover getCode in a bit. The important thing is that this is the end of the flow! At the end of getCode its going to trigger a reconnection of PlusClient, which will then connect us through the magic of cross platform seamless sign on. We'll build on this base as we address the other cases.

Returning Users

Returning users are awesome! We will get the seamless sign-in, so we can expect a PlusClient onConnected event. There are in fact two places we might get returning users - users that have used the app on this device before, and users who are seamlessly signing in having previously signed in on the web or another device. So, we just need to establish a session with the backend for these uses in the onConnected method if we don't already have one.

Note that we retrieve the account name from the PlusClient if we didn't already have it. Because of this, we will need the GET_ACCOUNTS permission in our Android manifest. If we don't have a session with the server, we'll establish one. This will also reconnect us, at which point we'll know we're fully signed in and can hide the sign in button and take other such actions. At that point, we have a session on the server, and both server and client authorised to make Google API calls.

Signed Out Users

We should offer sign out in our application. Usually this will be a method like this:

Note that we clear our prefs account name and stored session cookie as well as the PlusClient's account. If a user returns in this state, the server will have an refresh token for them, but the local client won't be connected. In that case, we just need to have them pick an account and all will be good.

Because both of these are going to be triggered by a user click and an account choice, our client needs to be a bit smarter. Now, in our activity result, we will treat it like this:

So we will initially try to retrieve a session. At the end of the session retrieval, we will reconnect. If that works, we're back in the returning users flow. If, however, the server does not have a refresh token, we won't be able to start a session. In that case, we'll get an onConnectionFailed while we have a set account name, and a known server session state. If we find ourselves in that condition, we can fetch the code. Note the hash we're using to track the server refresh token state - we'll fill that in createSession below.

The getCode will then trigger a reconnect, and we'll sign in as in the new user flow.

Get Session

One of the two main questions is how do we securely establish the session with the server. We do this by sending across the ID token for the account that has been selected. This allows the server to securely verify the Google user ID, check in its database whether it has a refresh token stored, and whether that refresh token is still valid.

There are two parts to the getSession functionality - retrieving the ID token, and sending it to the server. Both may involved network access, so these should be done off the UI thread. We'll create a private AsyncTask class to contain the fetching logic. We'll also need to define another constant - the client ID of the server that will be processing the ID token. Our getSession method will therefore just check whether there is a an existing session, and kick off the task if not.

The first part is just retrieving the ID token with the account name we have retrieved. We just need to pass a scope string with this particular formatting to the getToken method in GoogleAuthUtil, along with the client ID for the web server we will be sending it to. Retrieving the ID token doesn't trigger any user visible interaction.

You'll note we aren't doing a lot with the error handling here. There is a lot of scope for making a nicer user experience by managing these different cases. Particularly prompting the user to install Google Play Services, and so on. These will all be the same as in the regular Google+ Sign-In on Android implementations though.

Next we send the retrieved ID token to our server. Even though an ID token can't be used to access Google APIs, it should always be sent across HTTPS. This ensures it can't be snooped on by middlemen, and perhaps used to impersonate the user to your server. On the server side, we need to verify the ID token, extra the user ID, check whether there is a refresh token, and that the refresh token is still valid (generally by creating an access token, or checking a cached one). If that is true, then we can generate a session cookie and return it as the body of a response with a 200 request (we could of course return it in a header as well). Otherwise, the server returns a 401 to indicate it does not have a stored token.

In real applications it is preferable to do this type of checking on regular API calls, rather than having a separate session connection call as in this one. In this little sample though, we don't have any other API calls!

At the end of the async task we add a post execute method. If the retrieve was successful, we mark the status of that user on the server in the hashmap (indicating they do or don't have a refresh token on the server), and rebuild the PlusClient to be sure it includes the default account name. We then reconnect it, in order to trigger the next step.

At this point we will either get onConnected and be on our way, or we will get an onConncectionFailed need to get a refresh token for the server via the getCode method.

Get Code

Finally, we get to the part where we actually retrieve the code. You might be asking, why all the roundabout work beforehand? There are two constraints around managing the code:

  1. Retrieving a code will almost always display a consent dialogue.
  2. There is a limit to the number of refresh tokens a user may have for an application.
  3. For seamless sign in, the server must have exchanged the code for a token, and all scopes must match.

This means that if you were to get a code each time, you'd have to show the user the consent dialogue every time they signed in. It also means that if you exchanged that code each time, and never revoked any of the previously exchanged tokens you would eventually hit a limit where you couldn't retrieve any more tokens.

Just like with getSession we'll need to make a GoogleAuthUtil.getToken call to get the code, and an HTTPS call to the server to exchange it and set up a session. There is an extra complication in that we will have to deal with the consent screen. This will be shown if the user has not approved a consent screen for the code within a fairly short time span. We'll need to catch a UserRecoverableException and fire the Intent to allow the user to approve the application.

Note that here we are requesting just plus.login, but in general apps will want more than one scope, and these must match in all places. One common error when implementing multi-app systems is to have differing scopes, so its well worth defining these in a single place, and always referring to that string!

The normal flow when this code is executed is that it will throw the UserRecoverableAuthException. There will be a short period after retrieving the code where the code will be returned automatically, but that won't happen if the consent dialog was for a regular ConnectionResult resolution. We'll have the user sign in, and handle the result in the onActivityResult. All we need to do is fire the getCode task again, where this time the code retrieval should succeed:

When we need to get the code itself, we need to do something with it. Before we can reconnect we need to have the server exchange the code for a token. Before it has done this, we won't get seamless sign-in, which will mean the user would have to consent again. So, the server exchanges and sets up a session cookie for us at the same time.

Note: When exchanging the code on the server side, you don't need to pass a redirect_uri!

You'll note that we invalidate the code as soon as we have sent it. Whether it worked on not for the server, we want to consider that code burned. If we don't invalidate and go through the flow again, we'll just receive the same code back due to the local caching within Google Play Services. This is likely to cause some confusing errors! Calling this function requires the USE_CREDENTIALS Android permission.

In our post execute step we want to do exactly the same as on the ID token session retrieval, as we are expecting the same cookie back in the body. Once again, we will trigger a reconnection of the PlusClient. Since we have an existing session, cross client single sign on should fire and we will be smoothly signed in.

One More Thing

That should be the main error cases, but for comfort it would be good to cover the situation where you have a session, but for some reason PlusClient still results in onConnectionFailed. In that case, all we can do is resolve the ConnectionResult and deal with it like a regular Google+ Sign-In. This is most likely to happen because the user has got a refresh token from another client (such as web), but the scopes don't match the ones requested on Android.

To account for this, we can add a little code to our click handler:

And then in the activity result handle the new result - as always, just reconnecting the PlusClient.

Hopefully that gives you an example of what you can do! There's the full activity from this post all in one go in this Android Google+ sign-in hybrid flow gist as well - though this type of flow is so application specific please just don't drop it into your app and hope! For a more realistic example, watch out for samples coming soon as part of the official Google+ documentation.

Appendix

I actually don't think this is too complicated once you get it in code, but it is not the easiest flow to explain. If you come up with a better way, please blog it and let me know! For your amusement though, before writing this post I tried to write down the flow in a sensible way - it took me quite a few goes (the way its explained here is the diagram on the right):

Read More