Taking advantage of the new Apps Marketplace

Posted by Nick Johnson | Filed under openid, app-engine, python, coding, tech, apps-marketplace, aeoid

The recently unveiled Apps Marketplace has been getting a lot of attention lately, and a lot of people are wanting to know how they can integrate their App Engine app with it, making use of its integrated single-signon support. Today we'll go over what's required to get this working.

Apps Marketplace uses OpenID for SSO. Fortunately, we can use the openid library, which provides a Users-API-Lookalike interface, to support this in App Engine. There are two additional requirements for getting SSO to work in an Apps Marketplace app:

The realm defined in the application manifest must match the realm specified in the OpenID request.

The OpenID library must support the host-meta discovery method.

Handling the first of these is easy: The aeoid library sets the realm of an OpenID request, by default, to the domain that the request was made over, so all we need to do is use that same domain name as the realm in our app's manifest file.

The second is a little trickier. The 'janrain' python-openid library which aeoid and other Python-based solutions are based on does not support host-meta as a discovery mechanism for OpenID URLs. Let's analyze what this discovery method does, and see if we can find a way around it.

There are two tasks that this discovery method assists with. The first is determining the OpenID URL for a user, given only their domain (which is passed to us as a GET parameter by Google Apps). The second is fetching more information about a user, once their OpenID URL is known.

Since we know that anyone coming from Google Apps will be using the Google OpenID endpoints, we can actually bypass the first part of this discovery process altogether. Given the domain name passed in with the initial GET request, the OpenID URL to use is simply "https://www.google.com/accounts/o8/site-xrds?hd={{domain}}". By using this, we can completely skip the first part of the discovery process. You can see this in action in aeoid's demo app by visiting http://localhost:8080/apps_login?domain=yourdomain.com .

The second part of the discovery process is a bit tougher. When the python-openid library completes the initial authentication process, and finds it needs additional information about the user, it engages in another discovery process to determine where it should go for that information. This is where, ideally, it should start off by trying the host-meta discovery method, which permits discovery of this information even if the Apps user in question is not hosting their own discovery documents. Since all of this occurs deep inside the openid library, there's little we can do about it short of patching the library, either.

There remains one way around this, however: Have the Apps user host a standard openid discovery document on their domain. The openid library can then use its standard discovery methods for this second phase of discovery, and everything proceeds as planned. All that's required is that they place a file called 'openid' in the root of their domain - instructions are here. With that present, the openid library will complete authentication as normal, and Apps users will seamlessly be logged into your app, without any prompting required.

The solution presented here isn't ideal, unfortunately - some Apps users will have to host a discovery document that they previously didn't have to care about. Doing so is a fairly simple process, however, and until the python-openid library (and other similar libraries) add support for configurable discovery or the host-meta discovery method, this is likely the best option available.

Disqus