Tuesday 18 May 2010

Using OpenID in Java on GAE

After a week of reading and searching through diverse blogs and discussion groups, here are my findings:

Google App Engine (GAE) is supporting the Google Account API. My understanding is that the OAuth protocol is used. Hence in this blog I will refer to it as OAuth. Additionally, GAE is also supporting the OpenID schema, referred as the [Experimental] Federated Login (the word "[Experimental]" is being added in the release 1.3.4)

The User API is providing methods for obtaining information about the authenticated user, as well as the redirection URL's for logging in and out.

Here is the example how it is being used in the Authentication DemoApp running on http://super-easy.appspot.com

UserService userService = UserServiceFactory.getUserService();

User user = userService.getCurrentUser();

String logoutURL = userService.createLogoutURL(destinationURL, authDomainMap.get(provider));

String loginURL = userService.createLoginURL(destinationURL, authDomainMap.get(provider), federatedIdentityMap.get(provider), attributesRequest);
where the authDomainMap and the federatedIdentityMap are defined like:

Map authDomainMap = new HashMap();
authDomainMap.put(ProviderEnum.Google, "google.com");
authDomainMap.put(ProviderEnum.Yahoo, "yahoo.com");

Map federatedIdentityMap = new HashMap();
federatedIdentityMap.put(ProviderEnum.Google, "https://www.google.com/accounts/o8/id");
federatedIdentityMap.put(ProviderEnum.Yahoo, "http://open.login.yahooapis.com/openid20/www.yahoo.com/xrds");
I would hope that there is a well defined way to obtain those two values automatically, knowing the provider of an OpenID, but currently my best is to hard code them.

Additionally, the last argument is a set of attributs requested, even thought it looks more like OpenID configuration (will investigate further):
Set attributesRequest = new HashSet();
attributesRequest.add("openid.mode=checkid_immediate");
attributesRequest.add("openid.ns=http://specs.openid.net/auth/2.0");
attributesRequest.add("openid.return_to=http://super-easy.appspot.com");
Currently I am getting the following data when authenticated with my Google account:
adminFlag: True
authDomain: https://www.google.com/accounts/o8/ud
email: drasko.kokic@googlemail.com
federatedIdentity: https://www.google.com/accounts/o8/id?id=AItOawl5p-d5O-OFO4Lv2iNWsboV3jLWr1Bp1qk
nickname: drasko.kokic@googlemail.com
userId: 108555035464369674882
I am still not sure about the meaning of some fields but definitely sure that the nickname is wrong. I would really appreciate some pointers about it.

One more thing, when using the RPXNOW service, the following is the information obtained from my provider:
{"profile":{"googleUserId":"103067513055141045393","verifiedEmail":"drasko.kokic@googlemail.com","name":{"givenName":"Drasko","familyName":"Kokic","formatted":"Drasko Kokic"},"displayName":"drasko.kokic","preferredUsername":"drasko.kokic","providerName":"Google","identifier":"https:\/\/www.google.com\/accounts\/o8\/id?id=AItOawkw-h3geWs619E2MYmexqY2W5FjdL-cBbo","email":"drasko.kokic@googlemail.com"},"stat":"ok"}