For a current (PHP) project I need a highly flexible authentication and permissions management system. Having heard plenty of mentions on the various PEAR lists I decided to try out LiveUser, which seems to currently be the most comprehensive such system for PHP. It’s a large codebase that seems to cover most of the necessary permutations and includes a number of prominent coders amongst its developers.
What I hadn’t taken into account, of course, was the lack of documentation. I spent quite a while trawling through their wiki and googling before concluding that the best way to work LiveUser out would be to work through the code piece by piece. And since that’s a long, slow process it seemed worth documenting here. I’m going to do that step by step, starting today with configuration and instantiation.
LiveUser’s initial configuration is managed through a large associative array that should be passed to the factory in order to instantiate the core object. Unlike some of the other arrays used as arguments to functions, this one is documented inline, but it still took a while to pick apart.
Here’s an example:
$liveuser_config = array(
First up we have some core parameters for LiveUser
autoInit determines whether or not the class tries to instantiate the various ‘containers’ when it is first called
'autoInit' => true,
the login parameter allows us to specify whether login should be attempted off-the-bat and whether or not the session ID should be regenerated after a successful login.
'login' => array( 'force' => true, 'regenid' => true),
With the core parameters set, we can move onto the ‘containers’. LiveUser employs containers to allow for flexibility. Containers can be thought of as ‘plugins’ that allow access to any sort of authentication or permissions management system you want to connect.
First up I define my permissions container. There are three container types that come with LiveUser out of the box: ‘simple’, ‘medium’, and ‘complex’. I’m looking for as much flexibility as possible so am using ‘Complex’.
We then provide some ‘storage’ parameters. LiveUser provides several storage option for permissions (primarily PEAR::DB, MDB and MDB2) and you can add extras in. Here I am using PEAR::DB and so specify a DSN and the prefix I’m using for my tables.
If I already had a DB object instantiated, I could remove the ‘dsn’ parameter and replace it with ‘connection’ which would be a reference to my existing connection.
'permContainer' => array( 'type' => 'Complex', 'storage' => array( 'DB' => array( 'dsn' => $dsn, 'prefix' => 'liveuser_'))),
For me, one of the key draws of LiveUser for me was the fact that I could authenticate against multiple sources for one application. This application includes a directory for a membership-based organisation, and I want all members to be able to login. There are also a few administrators who are not members, but need to be able to log in to the site.
authContainers is itself an associative array, with the keys being the names by which you want to address the different authentication sources. In this case ‘members’ and ‘admins’. You can specify a few options that should be familiar to anyone who’s used PHP’s sessions and then a few others. I’m again using the PEAR::DB interface for my authentication so I specify type as ‘DB’.
Options for the DB container are then given in the ‘storage’ parameter. As with the permissions, ‘dsn’ can be replaced with ‘connection’. ‘alias’ is an array that maps the table (‘users’) and fields that LiveUser’s DB container uses by default to the table and fields that we have in our application.
'authContainers' => array( 'members' => array( 'type' => 'DB', 'loginTimeout' => 0, 'expireTime' => 3600, 'idleTime' => 1800, 'updateLastLogin' => false, 'allowDuplicateHandles' => false, 'allowEmptyPasswords' => false, 'passwordEncryptionMode' => 'PLAIN', 'storage' => array( 'dsn' => $dsn, 'prefix' => '', 'alias' => array( 'users' => 'member', 'auth_user_id' => 'id', 'is_active' => 'status', 'handle' => 'username', 'passwd' => 'password'))), 'admins' => array( 'type' => 'DB', 'loginTimeout' => 0, 'expireTime' => 3600, 'idleTime' => 1800, 'updateLastLogin' => false, 'allowDuplicateHandles' => false, 'allowEmptyPasswords' => false, 'passwordEncryptionMode' => 'MD5', 'storage' => array( 'dsn' => $dsn, 'prefix' => '', 'alias' => array( 'users' => 'admins', 'auth_user_id' => 'id', 'is_active' => 'id', 'handle' => 'username', 'passwd' => 'password')))));
With that array set up, LiveUser can easily be instantiated using:
$live_user = LiveUser::factory($liveuser_config, $username, $password);
$live_user = LiveUser::singleton($liveuser_config, $username, $password);
and we can check whether the user is now logged in with
$live_user->isLoggedIn() which returns true if login succeeded, false if it failed.
(NB: LiveUser’s own database schema is distributed within the examples that come in the PEAR package. It is provided as an MDB-compliant XML file)