Friday, September 9, 2011

War Story: The Training Jump

One of the first things I did at my current job was to rewrite a Perl/CGI (the module, and the actual cgi-script execution model) site into PHP.  Part of this site implemented a single-signon (SSO) system for a partner site that hosts our training videos.  Clicking the link led to the innocuously-named "" CGI script.

The goal in life of the training_jump is to redirect a user to the partner site, passing along the username and email address.  The partner site creates the user if necessary, starts a session for them on its server, and ultimately displays the actual training content.

Inside training_jump is an innocuous-looking "use OAuth::Lite;" line.  I didn't know what OAuth was at the time, so of course I went and looked it up: OAuth is designed to let a site like ExampleMashup authenticate someone as "twitter user chris" without needing to ask chris directly for their twitter password.  Of course, this makes no sense, because in our case, we possess the account, not our partner.  Likewise, once the login is complete, the user should end at our partner's site rather than our own.  We have nothing to use the oauth token for, because we don't perform any operation at the partner site aside from the login.

Yet here inside training_jump was OAuth.  The user hit training_jump; we redirected to the partner by IP address (!) with the OAuth request token, all the necessary user data, a callback URL (training_jump again); they duly redirected; we collected the response token and redirected the user back to the partner with that token as the parameter.  The end result is still kind of fragile, in that AFAIK, it only works in the first browser you sign up with.  If you log in with Firefox, then try it in Chrome, the latter gives you an error somewhere along the line instead of videos.

IIRC, research at the time indicated that there was no good PHP OAuth library, and/or the suitable libraries didn't implement the exact flavor of OAuth API that was being used by the Perl code.  I'm absolutely certain I considered replacing the Perl entirely, but I don't remember why I rejected PHP OAuth as a solution.

I couldn't simply continue using training_jump as-is, because the CGI module and PHP store their session data in different locations, in different formats.  The username in the PHP session wouldn't be accessible to pass through the authentication dance, and it was clearly inadvisable to modify training_jump to accept a username as a URL parameter.

Nowadays, training_jump has been succeeded by the cleverly named training_jump2, which actually reads request variables on stdin and produces an answer on stdout.  (The format of this text is much like LiveJournal's ancient API, from back when I had a LiveJournal client.  There was no convenient interchange format, as the Perl code didn't have JSON installed at the time and PHP didn't have XML.  "Lightweight" eats you again.)  The PHP training_jump manages the connection between server environment and training_jump2, and training_jump2 simply had its server environment replaced with communicating over pipes.

We're in the negotiation phase of moving to the provider's newer platform, which has a proper, encrypted SSO system.  training_jump2 is slated to become irrelevant, eventually.  In the meantime, it's the only bit of Perl CGI that never made the jump to mod_php.

No comments: