Tuesday, April 25, 2006

Simple Single Sign-on Scheme

Single sign-on, or SSO, has become the Holy Grail of enterprise web applications and indeed, just like the mythical quest taken up by knights in medieval times, so there has yet to be found a unified standard to allow users to easily login across trusted web sites. The battleground is littered with the corpses of failed initiatives such as Microsoft's Hailstorm. The Liberty Alliance has churned out a number of PDFs but that seems to be the extent so far of their effort. On the open-source side, LID shows a lot of promise but without any major corporate sponsors, it's difficult to judge how successful it will be.

So lacking a working foundation to go on, I decided to strike out on my own. My requirements were simple in that a user would not have to create a separate account, the login procedure would not be a hindrance and above all it had to be secure. Too often in my dealings with vendors I've seen login schemes that easily allow a malicious user to spoof another user's identity and masquerade as somebody else on the site. With this lesson in mind, I went about detailing how it would all work.

We'll need to make some assumptions first. This scheme requires at least two entities. Entity A is the main organization, the one that holds all the users' account info. Entity B is a vendor that has agreed to interface with Entity A so that users will not have to create a second account to utilize Entity B's services. We must also assume that a user logs in with a user ID and password to access Entity A's site. That user ID must be unique and can be an email address or something auto-generated. As well, Entity A must have a service visible to the outside that can validate a user with their ID and password. The easiest method would be to have a web service that checks against an LDAP, RDBMS or some other data store.

The process begins when a user logs in to Entity A's site with their user ID and password. Once validated, a string is generated containing the user's ID and any other meta information Entity A may want to pass along to Entity B. This string is then encrypted using a key that has been pre-shared with Entity B. The resultant encrypted string is put through a Base64 encoding function and then URLEncoded to ensure that no characters are lost. This string is appended to a URL pointing to Entity B's site using an agreed upon CGI variable. This URL can be displayed as a link which the user can then click on.

Upon arriving at Entity B's site via the URL, the appended string is put through a reverse process (URLDecoded, Base64 decoded, decrypted using the same pre-shared key) and from that the user ID and any other attached meta information is made available. At this point, the user should see only an input field requesting their password. The other data can be put into hidden form fields which will be passed along when the user submits the form. When that form is submitted just the user ID and password will be passed back to Entity A but this time to a published web service to authenticate against. If the web service returns success, then the user is logged in. Otherwise, the user is routed back to Entity B's site but with an appropriate error message.

Simple really was the theme of this SSO implementation. Though it lacks the features of some of the more mature setups, it does have the advantage of being relatively easy to deploy. As well, the requirement that a user resubmit their password at Entity B's site means it can withstand a replay attack. And provided that employees at Entity A do not have direct access to users' passwords, they would not be able to login as another user either. You could increase the security even further by changing the pre-shared key every 90 days though even with the most basic Triple DES encryption a brute force attack would be impractical.

This scheme has been in production for over a month now on our member portal with no complaints or reported errors. This feat would not have been possible though without the help of some talented individuals. My colleague John K. proved invaluable when it came to brainstorming on this issue. And were it not for Mark H. at Workmode, my point man at the vendor, this project would not have gotten off the ground. Lastly, the encryption functionality was provided courtesy of DevX.com and was extremely easy to implement and use.

Please feel free to comment on this or email me if you have any questions.

Tuesday, April 18, 2006

Pretty URLs for SPGM

Since putting a photo gallery on my site I have always used SPGM, the Simple Picture Gallery Manager. It's a great application in that it does not require a database, is totally configurable and is very easy to manage. The latest version, 1.4.4, is mature and stable and I look forward to many more years of using it.

However, one thing that's always bugged me about it, and for that matter many other web applications, is the lack of pretty URLs. Now my favorite web framework does away with this issue entirely but web applications written in other languages such as PHP typically do not take this into account. Ugly URLs often do not get indexed by search engines, are more prone to linkrot, and just look darned ugly. So I decided to do something about it.

First, I went about upgrading my version of SPGM. Wow what a difference a year can make! Version 1.4.4 was quite a jump with newly updated themes and a really cool shadow effect that makes my pictures seem as if they are floating above the page. Aside from some minor stylesheet integration issues that I eventually fixed, the upgrade went very well.

My next task was to change the output of SPGM itself so that it would make every link a pretty URL. I started out by replacing every instance of '&', '=' and '?' with constant values named SEP_AMP, SEP_EQL and SEP_QM, respectively. I then defined a constant called PRETTY_URLS which, if set to true, would create URLs that looked like /spgm/spgmGal/gallery_name/spgmPic/picture_id. This modified version of the SPGM engine can be found on my website.

Lastly, I had to put my mod_rewrite skills to use to direct these pretty URLs to their correct locations. For instance, a link to /spgm/spgmGal/Spring_Break/spgmPic/3 would actually be a link to /spgm/index.php?spgmGal=Spring_Break&spgmPic=3. Also, because SPGM relies on relative links, mod_rewrite had to redirect image links from within the galleries in order to display the thumbnails properly. Eventually I was able to accomplish everything with just six RewriteRules in my .htaccess file.

RewriteEngine on
RewriteRule ([a-zA-Z0-9,_]+)/gal/(.*)$ /spgm/gal/$2
RewriteRule ([a-zA-Z0-9,_]+)/flavors/(.*)$ /spgm/flavors/$2
RewriteRule spgmGal/([a-zA-Z0-9,_]+)$ /spgm/index.php?spgmGal=$1
RewriteRule spgmGal/([a-zA-Z0-9,_]+)/spgmPic/([0-9]+)/spgmFilters/(.*)$ /spgm/index.php?spgmGal=$1&spgmPic=$2&spgmFilters=$3 [L,QSA]
RewriteRule spgmGal/([a-zA-Z0-9,_]+)/spgmPage/([0-9]+)/spgmFilters/(.*)$ /spgm/index.php?spgmGal=$1&spgmPage=$2&spgmFilters=$3 [L,QSA]
RewriteRule spgmFilters/$ /spgm

Both the .htaccess file and the modified version of the SPGM engine can be found bundled on my site. Please email me if you have any questions or comments on using it.

Wednesday, April 12, 2006

The Importance of Teamwork

What a cliché title that is. Unfortunately, I just couldn't come up with anything that was short, witty and as descriptive of the subject matter of this blog entry. Time and time again, teamwork has proven to be the most invaluable and yet undervalued resource. My college curriculum, great as it was, tended to focus on individual projects. The idea was that group projects encouraged laziness on the part of some allowing them to skate through the class without learning the material. To a certain degree that fear is realistic. But it also handicaps many graduates who end up working for companies where group projects are the only way to get things done.

With my former employer, I did not get into any major projects requiring the skills of multiple people. Most of my projects were small and specialized and could be accomplished in just a few months time by myself. But upon arrival at my current employer, it was clear that I had to throw out the old rules. My task was to give them a portal for our members that worked and there was no way I could learn a platform, much less an industry that was entirely new for me, in just a few months.

So I enlisted the help of analysts, data integrators and others from departments as varied as marketing. My address book quickly became quite the motley collection of contacts. But the synergy that developed between us enabled much more than just a quick turnaround on what seemed an impossible deadline. It created something that I had only dreamed of.

Nobody likes to see their work lambasted and I had to bite my lip several times when criticisms were aimed at what I thought were great ideas. Yet by incorporating this feedback into the product, I gained not only a better product but a group of people ready to evangelize the other departments on the quality and usability of it. For me, this automatic buy-in from the people on the team was quite the shock. It makes sense in retrospect but was not something I had personally experienced before.

Wednesday, April 05, 2006

The Joy of Blogging

I've been blogging for nearly six months now, much longer than I had anticipated I would still be doing it. I have found it to be a source of joy that I had previously all but forgotten about, namely writing. I used to do quite a bit of it in high school and in my early college days. But as my studies in computer science took up more and more of time, so my devotion to writing began to wane. The well-formed multi-page essays gave way to quick reactionary comments on Internet message boards. Quality gave way to quantity.

But now that trend has begun to reverse itself. While I still prowl my favorite boards sporting for indepth political discussions, I also make sure to set aside at least a few hours each week to blogging. Some of that time is spent pondering my next piece but a good chunk of it is used on editing what I've written. Spelling errors, grammar mistakes and misused tenses pepper my first drafts. Not only that but simply getting the wording right can take up to five or six drafts. Usually by then though, I feel that it is as polished as it's going to get.

I have also been putting my writing skills to use in the workplace. What should sound like dessicated documentation instead reads like a strange mixture of prose and programming. Though I doubt many will ever read those particular works, if I can manage to bring even a hint of a smile to some future employee who expected something much blander then I will be glad for it.

One other aspect of blogging that I've experienced firsthand recently is notoriety. It seems that some of my former co-workers have discovered the site and while most just lurk, one took the opportunity today to attempt to anonymously post a nasty and rather personal comment. I bolded anonymously because the Internet is anything but. Thanks to some excellent logging utilities I was able to get the physical location of the IP address and from there it was as simple as cross-referencing it with the Yellow Pages to discover the true identity of the culprit. What's funny is that this person had claimed to be my friend yet I knew otherwise. I can only hope that posting meaningless comments to my blog doesn't become a habit for her.

But let's not end this entry on such a down note. As it is, I shared this information with some of my other former co-workers and we all had a good laugh about it. It just goes to show that you can't take the Internet too seriously. The things people say from behind the thin veil of their browser window is rarely anything like what they would say to you in real life. So laugh about it and move on.

Here's to another six months of blogging!