Thursday, December 18, 2008

Google Friend Connect site authentication

OK. Here's the deal:

I want to use GFC to authenticate users for my site.

It sounds like it should be doable, right? I think it is, but at the moment it's kind of hard. In fact it's so hard (or I'm so soft) that I haven't been able to do it (yet). Let recap a bit what it is GFC (Google Friend Connect) does;

1. If you enable GFC for your site, you can add GFC widgets which let people comment and rate the page you add the widgets to and interact in various ways. You can also add any custom OpenSocial widget you like (AFAIK)

2. One of the widgets you must have is the login widget which let anybody 'join' your site. When they do so, Google open up a separate window which let them choose their method of authentication; Google, Yahoo, OpenId, et.c., with various suboptions in Google's case).

3. Now Google keeps track of unique users that act on the widgets on your site, let them unjoin, log in and out, and so on.

4. The original identity provider (Google, Yahoo, et.c.) is still used as always for changing password, user info, et.c.

This is really great. The immediate thought when realizing how things work is that you want somehow to leverage this great new functionality that Google provide: To have a secure, authenticated site where you don't need to manage anyones identity, password changes, et.c.

So, I started trying to do so.

The first easy thing was to create a custom OpenSocial widget on my own site, that I pull in using the custom widget option on the 'social gadgets selection' on the GFC admin site; .

What happens is that you let GFC generate a HTML snippet that loads an open social script from google, which in turn pulls in your script - through - google's proxy server. In any event, the script resides on a directory on your server, and get to land on you page (which was just recently in another directory) and can then suddenly utilize all GFC magic - check the id and name of current viewer, his/hers friend list, et.c. Neat.


If you just post this info back to your server using standard Ajax - and trust the info you get - you're lost. How can you be sure that it really was your script that send that info? No, you need to make Google's GFC server send certified info back to your server about the current viewer.

Luckily enough, there's an OpenSocial call called (..) makeRequest, which makes an ajax call through the Container (Googl'es GFC servers, in this case, since Google/GFC is the Container. The Container would normally be LinkedIn, MySpace, Orkut, et.c.) to any given destination. For example your server, which actually hosts the page where the GFC widgets are hopping about.

Is a great place to learn what can be done with this. For one thing, you can send back some good info. My simple OpenSocial script did just this, and made sure to begin in a nice and easy manner, not forcing any encryption, using AuthorizationType.NONE, like this;

var params = {};
params[] =;
params[] =;
params[] = 5;
var url = "http://xxxxxxxxxxxxx";
console.log("calling url... '"+url+"'");, reqcb, params);

function reqcb(data)
console.log("reqcb called....");

And this works well. Looking more carefully into the link above, one reads the following:

If opt_params[] is set to, the container needs to vouch for the user's identity to the destination server. The container does this by doing the following:

  1. Removing any request parameters with names that begin with oauth, xoauth, or opensocial (case insensitive).

  2. Adding the following parameters to the request query string:

    The ID of the current viewer, which matches the getId() value on the viewer person object.
    The ID of the current owner, which matches the getId() value on the owner person object.
    The URL of the application making the request. Containers may alias multiple application URLs to a single canonical application URL in the case where an application changes URLs.
    An opaque identifier used to distinguish between multiple instances of the same application in a single container. If a container does not allow multiple instances of the same application to coexist, this parameter may be omitted. The combination of opensocial_app_url and opensocial_instance_id uniquely identify an instance of an application in a container.
    An opaque identifier for the application, unique to a particular container. Containers that wish to maintain backwards compatibility with the opensocial-0.7 specification may include this parameter.
    An opaque identifier for the public key used to sign the request. This parameter may be omitted by containers that do not use public keys to sign requests, or if the container arranges other means of key distribution with the target of the request.
  3. Signing the resulting request according to section 9 of the OAuth specification.

So, if I could use a SIGNED request instead, the GFC proxy servers would add all the info I need and crave for my service, especially a guaranteed identity of the current page viewer. Using this unique id in my tables gives me to power to associate this identity with anything I'd like on my site. Ok. Fine.

What happens when I use SIGNED? Well, the callback function always gets back the verbose, detailed and informative error message "404: Not found", in a JSON object, but still..

Now you might think that I don't know the first thing about public cryptography, signing requests and tossing certificates about in the rich and useful variety of almost-compatible formats the joyful and friendly cooperation between related companies in the beginning of this century gave rise to, but you'd be wrong.

I can't call myself an expert (any longer), but I have quite a good working knowledge of the above. the problem here is that the documentation makes references to the public certificate of the container, which the receiving service need to verify.

great, but the Container is GFC. Where's their certificate? Maybe this is obvious, I don't know. It isn't for me, anyway. Reading another page which digs deep in the OAuth spec, I find a links I've never seen before, which let me register sites with google and deploy their public certificates;

Has some links that lead to the registration page for web-based applications;

So I do just that, and use the OAuth playground;

to verify that things (seem to work).

Now, I'm not sure that my site, not being an OpenSocial container (surely!) need to register a certificate with Google, but just in case this was needed to make the SIGNED request work, I did so and played around with it.

No luck. The result stays the same; "404: not found". Great.

What I (and possibly **ALL** other site owners starting to use GFC) need, is some information. Anything of the below will be fine, if not else to give some info back to the community instead of the usual Google no-walling;

1. Here's a simple example which demonstrates how to write a simple OS gadget which post back the current viewers unique id and info.
2. Rick caught the flu last week and haven't had the time to write the example. We'll get on it in a couple of weeks.
3. We'll never give that information, stupid Englishmen! Go and boil your bottoms, sons of a silly person!
4. It's impossible to do what you want. Go back to bed.
5. Wow, that's an interesting idea. We hadn't thought of that! We'll get back to you..

Having emptied my reservoir of frustrated incompetence, I must end with stating the fact that despite all the trouble I've had in trying to get the site authentication to work, I've at least got my money's worth :)


Kevin Marks commented on one of my posts on the open social mailing list that GFC does not support signed requests at the moment. We got a number 4!! Yay! Thanks for the info, and let's hope that this gets added real soon.


Saturday, December 13, 2008

Towards a better integration of i18n in Dojo widgets

Maybe this is old hat to some, but I've been doing some research into i18n and come up with what I think is an interesting way to get better integration with internationalization in layout containers.

To recap, Dojo has, and uses internally, an internationalization system which makes sure that the Cancel button button read 'Anulla' if your browser says that your locale is 'it', and so on.

I have been thinking about various ways of making the use of i18n more dynamic. My first stab at this was a small widget, which could be embedded in a page (at any amount of places) which treated its innerHTML as a key string to be looked up in the i18n system and exchanged for the actual message du jour.

This was a rather heavyweight solution (and I also wrongly used dojo.requireLocalization inside the widget, instead of by the dojo.require statements where it should be. It was just insane to do that every time an instance of the widget was created, but that's how I roll :), and was unable to handle translations of html properties, like the title="" inside an anchor element, for example.

I then thought of extending dijit._Templated (the superclass of all Dojo widgets whichuses 'normal templates) to do roughly the same for all all widget templates. But somehow it felt not really spot on for my problem.

What I had, was a number of pages, which I had been translating to a number of hmtl 'snippet' files, which only contained the markup for what they wanted to do - no body, header or stuff like that. They are used inside ContentPanes which are managed in turn by a StackContainer, which simulates page transitions but within preloaded html snippet, getting you a mighty quick site where all parts are already loaded in the browser,but only one shown at a time.

Each of these 'pages' have a lot of text, which should be translated, as well as a number of title="" and related element properties which also should be translated, so having a solution which only worked for widget templates would only solve part of the problem.

SP what Idid was to create a widget which sublassed dijit.ContentPane, and which overrode the function called when the pane is done loading remote content (the file containing the html snippet), onDownloadEnd.



dojo.declare("layout.TranslationPane", dijit.layout.ContentPane,
onDownloadEnd: function(pane)
console.log("layout.TranslationPane callback onDownloadEnd called.");
var html = this._getContentAttr();
var res = dojo.i18n.getLocalization("layout", "salutations");
html = dojo.string.substitute(html, res);
this._isDownloaded = true;

Not much code? No, that's because I solve my problems a) at the machine they appear, b) in JavaScript, and c) on the shoulders of Dojo. So there.

That leave me with snippet files which contain any number of ${title_of_stuff} anywhere at all, since the 'page' is treated as a string.

I think that this would be a great thing to add to ContentPane permanently, with a couple of extra properties to it, which would point out locale overide and (not optional) the name of the package and translation file to use for any ${keywords} appearing in the markup loaded.



Monday, December 1, 2008

Sample chapter from my new book - Layout

Promotion is a strange thing. 

I mean, I have written this book and it would be nice if people read it. 

However, I'm no marketing expert and despite appearances, tend to be a bit dismissive of my achievements.

Having said that, let me tell you what's great about the book I wrote;

1) It's just 250 pages long
2) It covers in the most approachable way I could write about it - not common :)
3) It delves into as many parts of dojox as I could muster, not just the usual stuff but DragPanes, ExpandoPanes and GridContainers, with examples and tutorials as well.
4) Uses a lot of the actual (svn) source code of Dojo to show and explain different kinds of funcitonality.
5) Describes the creation of custom Dojo widgets at every opportunity.
6) Heavily opinionated.

That's not enough for you, eh? OK, grab a sample chapter on layout right here, and tell me what you think. No really, please mail me so I get some feedback on how usable it is to actually learn Dojo, since that's what the title is about, isn't it?