Latest News

NOTE: The full code archive of mechanism described below can be found here
Joomla is a PHP-based CMS that enjoys wide-spread popularity. It's got a many built-in features that make it great for blogs and news-oriented sites right out of the gate. Additionally, it supports three kinds of extension mechanism: components, plugins and modules. Components are low-level facilities that generally support the other two. Modules are often user-visible blocks of HTML that can be selectively added to the page users see. Plugins respond to various events (page rendering, authentication requests, etc) generated by the Joomla application.
Joomla comes with a variety of login plugins that all use the login module. These plugins allow users to be validated against an external authentication mechanism like LDAP or GMail.
Sometimes it is desirable to log users into the Joomla system who have already been authenticated by a different system without asking for their credentials again. This is called signle sign-on (SSO). SSO is a very important usability and security feature of many Service-Oriented Architectures (SOA). In this article, I will present a token-based mechanism for creating SSO to joomla using the standard extension methods.
To understand this problem a bit better, it is critical to realize that there are two seperate notions of identity in an SSO schema. There is the previously authorized identity (that is, the identity that the user supplied to the non-Joomla system that originally authenticated them) and the user account on the Joomla system that is stored in the local users table. One of the challenges of SSO is to map the remote identity to the local one. For the sake of this excerise, let's assume that the usernames in both the remote authentication system and the local Joomla one are the same.
The next problem is to create a protocol by which authentication credentials may be passed from the remote system to the local Joomla one. To accomplish this, I choose to use to copy the existing mod_login form and make some minor adjustments to accept HTTP GET parameters. These GET parameters are translated into values in a form that can be processed by the default user compoent. Since the user component calls out the enabled authentication plugins, this the kind of routing is desirable.
This form really needs three bits of information to authorize a user: the username, the session token and a checksum. The username is self-evident. The session token is provided to all authenicated requestors and is discussed more later. The check sum is hash of the username, token and a shared secret known to this system and the remote system passing users to it. More on this later too.
Using a bit of javascript magic, this hidden form is submitted automatically.
Of course, a custom authentication plugin is also required. The plugin needs to read a few of the custom form values that are not passed in through the normal onAuthenticate() call, so it is necessary for the plugin to directly read from the superglobal $_POST. The job of this plugin is very simple. If the token is valid (that is, it can be found in a DB table and is younger than 4 hours) and the hash value of the username, token and shared secret matches the given hash, then the user is authenticated. The user is found in the local system and the response object is populated accordingly.
The session token can be any string identifier. In this case, it is the MD5 hash of the value returned by the PHP built-in uniqid(). This value is generated by a script called 'session.php'. The script generates this value, stuffs it into a DB table and simply echoes the value to the caller.
The key to the security of this system comes from the secret string known only to the remote system that wishes to pass users to the local Joomla system and authentication plugin. This secret is used to generate a hash of the usernam and the session token. By using a hashing mechanism like MD5 or SHA1, this checksum value provides pretty good assurance that the values passed in were from a known and trusted source.
The way the remote system and the Joomla system interact to make this autologin happen is the follow:
- The remote client calls the session.php script on the local Joomla system
- The remote client hashes the session token, username and secret
- The remote client generates a URL to the local Joomla system's homepage that passes in the following GET parameters: u, t, s (for username, token and checksum respectively)
- The remote client redirects the user to this URL
- If the token is authenticated, the user is logged into the local Joomla system as a local Joomla user.
You'll also notice that you could easily map all remote users to one generic Joomla user if that is desirable.
I hope you find this useful in crafting your own Joomla solutions
Security, it is said, is a process, not a product. For every method of securing information from unauthorized eyes, there is (or will be) a counter measure. There are two aspects of security: authentication and authorization. Authentication is concerned with determining the identity of user wishing access to a secured resource through the use of some kind of credentials. Authorization is the set of rights a user has over a secured resource. In Unix terms, a user's account name and password as stored in the file /etc/passwd are the authorization credentials needed to log into the system. The permissions on files and directories represent the authorization mechanism.
In the world of web services, the need for authentication and authorization is clear. For example, twitter.com allows a user to update his status through a public API. However, only the owner of that account should be allowed to make updates. Reusing an existing authentication/authorization mechanism, Twitter's API expects account credentials to be passed through the basic authorization method of HTTP.
An even more secure authentication/authorization mechanism is X.509 PKI standard in which clients and servers exchange encrypted credentials that identify themselves to each other. Each certificate has a "web of trust" or chain of authorizing servers that can be consulted to establish the validity of its origin. Setting up this web of trust, however, can be a daunting task.
Some applications may simply wish to hide information from authorized eyes without the complexity of a full PKI implementation. One old cryptographic technique to do this is the Vigenere cipher, whose origins date back to sixteenth century (although the name come from a nineteenth century diplomat). The Vigenere cipher is a novel twist on the very ancient caesar cipher.
A caesar cipher works by substitution a letter of the plain text message with a different letter of the alphabet. The substition is not random, but represents a constant "shift." To understand a shift, image an ordered list of the capital letters from 'A' to 'Z', where 'A' occupies position 0 and 'Z' is at position 25. A shift is a function that takes a plain text letter, adds a fixed amount of position and returns the letter at the new position. For example, shift('A',1) would produce 'B' and shift('Z', 1) would produce 'A'. To decrypt a caesar encrypted message easily, you need to know the alphabet used and the shift amount.
ILIKEPIECaesar(2):
XAXZTEXT
Caesar ciphers were used heavily for centuries, but are not particularly secure because they do not change the frequency of occurence of letters. In languages with alphabets, some letters occur more frequently than others. In English, the most common letter is 'e'. If caesar-encypted text is long enough, whatever letter presents 'e' will also appear often. One can then workout the shift and from there the rest of the message in a process that resembles "Wheel of Fortune."
For the curious, here's a snippet of Perl that represents the shift function:
sub encode {
my ($s, $shift) = @_;
my @parts = split //, $s;
my $t = "";
for my $p (@parts) {
$t .= chr(ord('A') + ((ord($p) + $shift) % 26));
}
return $t;
}
To decode a caesar inciphered message, the following function will work:
sub decode {
my ($s, $shift) = @_;
my @parts = split //, $s;
my $t = "";
for my $p (@parts) {
$t .= chr(ord('A') + ((ord($p) - $shift) % 26));
}
return $t;
}
Next time, we'll look at how to implement a Vigenere cipher in Perl.
More early Pete Gabriel madness. Also a plus for those who think samplers are too complicated these days.
About this blog
The taskboy blog is a exploration of computer technology by Joe Johnston. Topics of posts include practical examples Perl, PHP, Python and Java as well as book reviews, industry insights and miscellaneous good stuff.
Current Status
Watching _Brass Latern_. Ah IF, your coyness is your charm.
Posted: Sun Sep 05 16:02:15 +0000 2010
Latest Feedbag
- Reader recommendation: Atlas, Schmatlas
- Scientists Cut Greenland Ice Loss Estimate By Half
- (Video) George Parker: Agencies Need To Buy Themselves Back
- Android Is As Open As The Clenched Fist Id Like To Punch The Carriers With
- Eden Ventures Joins The Super Angels Gang, Five Investments Down
- Human Translation Startup myGengo Raises Seed Round From International Investors
- Another Instant Music Video
- DARPA Wants Extreme Wireless Interference Buster
- Film Industry Hires Cyber Hitmen To Take Down Pirates
- Online Football Game Quick Hit Relaunches With Official NFL License
Generated: 04:22 on 09/Sep/2010
Recent posts
- Very quick git primer for basic functionality
- Tips for spammers: don't insult me
- CakePHP vs. Symfony: a quick note
- Creating events for Yahoo and Google calendars
- SANs on a budget: iSCSI under Ubuntu
- iPad, iTouch and Kindle: Which is the better mousetrap?
- Rise of the Ad-Hocracy, Part II
- Rise of the Ad-Hocracy, Part I
- Small Hiatus
