Note: This article applies to Joomla! 2.5.17 and earlier. For version 2.5.18 and higher, see this note
Xataface is able to use the joomla users table to authenticate against so that, you can allow your users to log into your Xataface application using the same credentials as they use to access your joomla website. Achieving this level of integration requires 2 simple steps : 1 - Set up the [_auth] section of your conf.ini file to reference the joomla users table and the correct username and password columns. 2 - Create a delegate class for the joomla users table to be able to decrypt the password set in the table.
Configure the conf.ini file
Joomla users table is named jos_users. So you have to declare this table in the conf.ini file.
So it's a great encryption but xataface doesn't know how to do that. Here is the utility of the delegate class. We will define a function inside which could compare the entered password in xataface with the joomla stored password.
Creating the delegate class
1 - Add a jos_users directory in your directory table 2 - Create a jos_users.php file inside this new directory
Creating the decrypt password function
Before posting this code, I would like to thank fantomasdm who created this function. So here is the code of the function to paste directly in the jos_users delegate class :
<?
class tables_jos_users {
function password__serialize($password){
$app =& Dataface_Application::getInstance();
$query = "SELECT id, gid, block, password, usertype FROM jos_users where username='".$_POST['UserName']."'";
$result = mysql_query($query,$app->db()) or die("Query failed" . mysql_error() );
$line = mysql_fetch_array($result, MYSQL_ASSOC);
mysql_free_result($result);
$arraypass=explode(":", $linea['password']);
$key=$arraypass[1];
$ret = md5(trim($password).$key).":".$key;
return $ret;
}
}
?>
Anyone using Joomla ver 2.5 and the Joomla users table for authentication in to their Xataface app needs to be aware that the Joomla password hashing changed as of version 2.5.18. This also brought 2.5.x in line with the latest Joomla version 3.x (so the following also applies for version 3.x).
Essentially, Joomla now uses PHPass to replace the bespoke hashing routine used before. This means the routine above is probably redundant for you if you've installed all the recommended (security) updates. One problem you may encounter is that existing users' passwords are converted upon logging-in, however if you have users that access your Xataface app directly, they may not have had their password converted whereas others will. This means that you need a routine that handles both old and new formats. Thankfully, the new routine uses a prefixed identifier to flag it as a PHPass hash.
The following is a sample users table delegate class that should work with a Joomla! Users table and deal both types of password hash. Adapted from https://groups.google.com/d/msg/xataface/8DlkolDYkR4/RCuZxX91qFwJ?
<?
class tables_your_joomla_table_prefix_users {
function password__serialize($password){
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$app =& Dataface_Application::getInstance();
$query = "SELECT id, block, password, usertype FROM your_joomla_table_prefix_users where username='".$_POST['UserName']."'";
$result = mysql_query($query,$app->db()) or die("Query failed: " . mysql_error() );
// $row = mysql_fetch_assoc($result);
$line = mysql_fetch_array($result, MYSQL_ASSOC);
/* Release resources */
mysql_free_result($result);
$arraypass=explode(":", $line['password']);
$key=$arraypass[1];
if (substr($line['password'],0,3) == '$P$') {
$hash = $this->_hash_crypt_private($password, $line['password'], $itoa64);
return $hash;
}
else {
$ret = md5(trim($password).$key).":".$key;
return $ret;
}
}
function _hash_crypt_private($password, $setting, &$itoa64)
{
$output = '*';
// Check for correct hash
if (substr($setting, 0, 3) != '$H$' && substr($setting, 0, 3) != '$P$')
{
return $output;
}
$count_log2 = strpos($itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30)
{
return $output;
}
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8)
{
return $output;
}
/**
* We're kind of forced to use MD5 here since it's the only
* cryptographic primitive available in all versions of PHP
* currently in use. To implement our own low-level crypto
* in PHP would result in much worse performance and
* consequently in lower iteration counts and hashes that are
* quicker to crack (by non-PHP code).
*/
if (PHP_VERSION >= 5)
{
$hash = md5($salt . $password, true);
do
{
$hash = md5($hash . $password, true);
}
while (--$count);
}
else
{
$hash = pack('H*', md5($salt . $password));
do
{
$hash = pack('H*', md5($hash . $password));
}
while (--$count);
}
$output = substr($setting, 0, 12);
$output .= $this->_hash_encode64($hash, 16, $itoa64);
return $output;
}
/**
* Encode hash
*/
function _hash_encode64($input, $count, &$itoa64)
{
$output = '';
$i = 0;
do
{
$value = ord($input[$i++]);
$output .= $itoa64[$value & 0x3f];
if ($i < $count)
{
$value |= ord($input[$i]) << 8;
}
$output .= $itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count)
{
break;
}
if ($i < $count)
{
$value |= ord($input[$i]) << 16;
}
$output .= $itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count)
{
break;
}
$output .= $itoa64[($value >> 18) & 0x3f];
}
while ($i < $count);
return $output;
}
}
?>