Custom Authentication Tutorial

A brief overview of create a custom authorization of users without hacking

Created by: spiderr, Last modification: 17 Apr 2009 (07:45 UTC) by Lester Caine
For our purposes, let's assume we work for company "Foo" and we need to write a completely custom authentication piece. What follows is the super cool way to do this with ReleaseTwo and leave all exsting source pristine.

Step 1: Create your custom package


All we need from that tutorial are steps 1 and 4 (a directory and a bit_setup_inc.php - tables are not required). Assume we make a package called foocore. Your foocore/bit_setup_inc.php should look something like:


global $gBitSystem, $gBitSmarty;
$registerHash = array(
    'package_name' => 'foocore',
    'package_path' => dirname( __FILE__ ).'/',
);
$gBitSystem->registerPackage( $registerHash );

if( $gBitSystem->isPackageActive( 'foocore' ) ) {
    // FooUser is our instantiated users class
    require_once( FOOCORE_PKG_PATH.'FooUser.php' );
    $gBitSystem->setConfig( 'user_class', 'FooUser' );
}


Step 2: Create a custom class that overrides the default bitweaver user, BitPermUser. This file will be foocore/FooUser.php



// It is likely this gets included prior to scanning users/bit_setup_inc.php
$userDir = dirname( dirname( __FILE__ ) ).'/users/';
require_once( $userDir.'BitPermUser.php' );

class FooUser extends BitPermUser {
    function BitPermUser() {
        parent::BitPermUser();
    }

    function login( $pLogin, $pPassword ) {
        if( $somethingProprietaryNeedsDoing ) {
            if( proprietary_authorize( $pLogin, $pPassword  ) ) {
                $this->synchronizeBitUser( $matches[1], $pLogin, $pPassword );
        } else {
            // we can use standard bitweaver auth process
            $ret = parent::login( $pLogin, $pPassword );
        }
        return $ret;
    }

    function synchronizeBitUser( $pUserId, $pLogin, $pPassword ) {
        if( $this->verifyId( $pUserId ) ) {
            $userRow = $this->mDb->getRow( "SELECT * FROM `".BIT_DB_PREFIX."users_users` WHERE `user_id`=?", array( $pUserId ) );
            if( empty( $userRow ) ) {
                // This is the first time this person has been synchronized. unset mUserId so a clean store goes through
                $this->mUserId = null;
                $this->mContentId = NULL;
                $this->mInfo = array();
            } else {
                $this->mUserId = $pUserId;
            }
            $propUserInfo = $this->getProprietaryUserInfo( $pUserId );
            if( !empty( $propUserInfo['user_name'] ) ) {
                $storeHash['user_id'] = $pUserId;
                if( empty( $userRow['login'] ) || $userRow['login'] != $pLogin ) {
                    $storeHash['login'] = $pLogin;
                }
                $storeHash['password'] = $pPassword;
                if( empty( $userRow['real_name'] ) || $userRow['login'] != $pLogin ) {
                    // we have a "Last, FIrst" name in our prop db
                    list( $lastName, $firstName ) = explode( ',', $propUserInfo['name'] );
                    $storeHash['real_name'] = trim( $firstName.' '.$lastName );
                }
                $storeHash['registration_date'] = strtotime( $propUserInfo['create_date'] );
                $storeHash['email'] = strtotime( $propUserInfo['email'] );
                $this->store( $storeHash );
            } else {
                $this->mErrors['login'] = "Unknown Proprietary user:".$pUserId ;
            }
        }
        return( count( $this->mErrors ) == 0 );
    }

    function getProprietaryUserInfo( $pUserId ) {
        return( ...SELECT SOME STUFF FROM YOUR DB.... );
    }

}


Step 3: Adjust bitweaver configuration

We need to make sure foocore is scanned before the UsersPackage so add the following to your kernel/config_inc.php:

$gPreScan = array( 'kernel', 'foocore', 'users', 'liberty' );