Solving problems with Google multiple sign-in on App Engine

App Engine’s integration of Google Accounts functionality generally works very well, however, it doesn’t have any direct support for Google’s multiple accounts feature. So if a user is signed into multiple Google accounts in their browser, then there is no easy way to give them the option to choose which of their accounts is used with your App Engine application.

This is especially troublesome if you need them to sign in with a specific account, e.g. if you have a whitelist of admin users, or you’re using verification URLs which have tokens tied to specific accounts, and therefore you need them to use a specific one.

But as App Engine doesn’t have direct support for Google Accounts’ multiple sign in feature, providing the user with a way of switching which of their Google accounts is used to authenticate with your app is a little bit tricky. But it is possible, read on...

Here is the behaviour

  • If a user is signed into multiple Google accounts, then sending them to a URL generated from users.create_login_url will show them the dialogue which lets them choose which account to use.
  • But if the user is not signed into multiple Google accounts (they just have separate Google accounts which are not linked together), then sending them to the URL generated by users.create_login_url will just redirect them straight back to your site. No good.
  • So if the user is not signed into multiple Google accounts, then you need to send them to a URL generated by users.create_logout_url so that they can then sign in again with the desired account.
  • However, if a user is signed into multiple Google accounts, then sending them to a URL generated from users.create_logout_url will log them out of all of their accounts. So any Gmail/Calendar/Drive/Google+ pages that they had open will be logged out. That’s no good either.

So in order for the user to switch accounts, we need to use either users.create_login_url or users.create_logout_url, but which one depends on whether or not the user is using the multiple accounts feature, which is something which we don’t know, until we try.

The plan of attack

  • We store the user’s current account ID or email in a cookie or session.
  • We redirect the user to users.create_login_url(). If they come back signed into a different account (checked against their session), then we know they are using the multiple accounts feature and they have now selected a different account. Done. But if they are redirected straight back, still logged into the same account, then we know they are not using Google’s multiple accounts feature.
  • Because we know the user was sent back with the same account we can immediately trigger the alternative redirect chain:
  • We now send them along a chain of Log out --> Log in --> Return to App Engine. E.g. users.create_logout_url(users.create_login_url()). This should log the user out of whichever Google account they are logged into, and then send them back to the login screen where they can log in with a different account, and then return to our App Engine app.
  • The entire process is transparent to the user, the only difference being more redirects if they not using multiple linked accounts.

Here’s the full code example

(This assumes you’re using Django views and sessions, but the principal is the same with webapp.)

By Rob K and Adam A