diff --git a/include/class.auth.php b/include/class.auth.php
index 09c1a4c8f6993a2dca9267cc0a2f4220fd4de805..3071cd424b9493a19a137066dde710f1291178fb 100644
--- a/include/class.auth.php
+++ b/include/class.auth.php
@@ -44,15 +44,25 @@ interface AuthDirectorySearch {
  * receives a username and optional password. If the authentication
  * succeeds, an instance deriving from <User> should be returned.
  */
-class AuthenticationBackend {
-    static private $registry = array();
+abstract class AuthenticationBackend {
+    static protected $registry = array();
     static $name;
     static $id;
 
+
     /* static */
     static function register($class) {
-        if (is_string($class))
+        if (is_string($class) && class_exists($class))
             $class = new $class();
+
+        if (!is_object($class)
+                || !($class instanceof AuthenticationBackend))
+            return false;
+
+        return static::_register($class);
+    }
+
+    static function _register($class) {
         // XXX: Raise error if $class::id is already in the registry
         static::$registry[$class::$id] = $class;
     }
@@ -65,24 +75,28 @@ class AuthenticationBackend {
         return static::$registry[$id];
     }
 
-    /* static */
-    function process($username, $password=null, &$errors) {
+    static function process($username, $password=null, &$errors) {
+
         if (!$username)
             return false;
 
-        $backend = static::_getAllowedBackends($username);
-
-        foreach (static::$registry as $bk) {
-            if ($backend && $bk->supportsAuthentication() && $bk::$id != $backend)
+        $backends =  static::getAllowedBackends($username);
+        foreach (static::allRegistered() as $bk) {
+            if ($backends //Allowed backends
+                    && $bk->supportsAuthentication()
+                    && in_array($bk::$id, $backends))
                 // User cannot be authenticated against this backend
                 continue;
+
             // All backends are queried here, even if they don't support
             // authentication so that extensions like lockouts and audits
             // can be supported.
             $result = $bk->authenticate($username, $password);
-            if ($result instanceof AuthenticatedUser) {
-                static::_login($result, $username, $bk);
-                $result->backend = $bk;
+
+            if ($result instanceof AuthenticatedUser
+                    && (static::login($result, $bk))) {
+                $result->setBackend($bk);
+
                 return $result;
             }
             // TODO: Handle permission denied, for instance
@@ -91,6 +105,7 @@ class AuthenticationBackend {
                 break;
             }
         }
+
         $info = array('username'=>$username, 'password'=>$password);
         Signal::send('auth.login.failed', null, $info);
     }
@@ -98,19 +113,17 @@ class AuthenticationBackend {
     function singleSignOn(&$errors) {
         global $ost;
 
-        foreach (static::$registry as $bk) {
+        foreach (static::allRegistered() as $bk) {
             // All backends are queried here, even if they don't support
             // authentication so that extensions like lockouts and audits
             // can be supported.
             $result = $bk->signOn();
             if ($result instanceof AuthenticatedUser) {
-                // Ensure staff members are allowed to be authenticated
-                // against this backend
-                if ($result instanceof Staff
-                        && !static::_isBackendAllowed($result, $bk))
-                    continue;
-                static::_login($result, $result->getUserName(), $bk);
-                $result->backend = $bk;
+                //Perform further Object specific checks and the actual login
+                if (!static::login($result, $bk))
+                    continue
+
+                $result->setBackend($bk);
                 return $result;
             }
             // TODO: Handle permission denied, for instance
@@ -131,57 +144,6 @@ class AuthenticationBackend {
         return $users;
     }
 
-    function _isBackendAllowed($staff, $bk) {
-        $sql = 'SELECT backend FROM '.STAFF_TABLE
-            .' WHERE staff_id='.db_input($staff->getId());
-        $backend = db_result(db_query($sql));
-        return !$backend || strcasecmp($bk::$id, $backend) === 0;
-    }
-
-    function _getAllowedBackends($username) {
-        $username = trim($_POST['userid']);
-        $sql = 'SELECT backend FROM '.STAFF_TABLE
-            .' WHERE username='.db_input($username)
-            .' OR email='.db_input($username);
-        return db_result(db_query($sql));
-    }
-
-    function _login($user, $username, $bk) {
-        global $ost;
-
-        if ($user instanceof Staff) {
-            //Log debug info.
-            $ost->logDebug('Staff login',
-                sprintf("%s logged in [%s], via %s", $user->getUserName(),
-                    $_SERVER['REMOTE_ADDR'], get_class($bk))); //Debug.
-
-            $sql='UPDATE '.STAFF_TABLE.' SET lastlogin=NOW() '
-                .' WHERE staff_id='.db_input($user->getId());
-            db_query($sql);
-            //Now set session crap and lets roll baby!
-            $_SESSION['_staff'] = array(); //clear.
-            $_SESSION['_staff']['userID'] = $username;
-
-            $user->refreshSession(); //set the hash.
-
-            $_SESSION['TZ_OFFSET'] = $user->getTZoffset();
-            $_SESSION['TZ_DST'] = $user->observeDaylight();
-        }
-
-        //Regenerate session id.
-        $sid = session_id(); //Current id
-        session_regenerate_id(true);
-        // Destroy old session ID - needed for PHP version < 5.1.0
-        // DELME: remove when we move to php 5.3 as min. requirement.
-        if(($session=$ost->getSession()) && is_object($session)
-                && $sid!=session_id())
-            $session->destroy($sid);
-
-        Signal::send('auth.login.succeeded', $user);
-
-        $user->cancelResetTokens();
-    }
-
     /**
      * Fetches the friendly name of the backend
      */
@@ -212,21 +174,148 @@ class AuthenticationBackend {
         return false;
     }
 
-    /* abstract */
-    function authenticate($username, $password) {
-        return false;
-    }
-
-    /* abstract */
     function signOn() {
-        return false;
+        return null;
     }
+
+    abstract function authenticate($username, $password);
+    abstract function login($user, $bk);
+    abstract function getAllowedBackends($userid);
+
 }
 
 class RemoteAuthenticationBackend {
     var $create_unknown_user = false;
 }
 
+abstract class StaffAuthenticationBackend  extends AuthenticationBackend {
+
+    static private $_registry = array();
+
+    static function _register($class) {
+        static::$_registry[$class::$id] = $class;
+    }
+
+    static function allRegistered() {
+        return array_merge(self::$_registry, parent::allRegistered());
+    }
+
+    function isBackendAllowed($staff, $bk) {
+
+        if (!($backends=self::getAllowedBackends($staff->getId())))
+            return true;  //No restrictions
+
+        return in_array($bk::$id, array_map('strtolower', $backends));
+    }
+
+    function getAllowedBackends($userid) {
+
+        $backends =array();
+        //XXX: Only one backend can be specified at the moment.
+        $sql = 'SELECT backend FROM '.STAFF_TABLE
+              .' WHERE backend IS NOT NULL ';
+        if (is_numeric($userid))
+            $sql.= ' AND staff_id='.db_input($userid);
+        else {
+            $sql.= ' AND (username='.db_input($userid) .' OR email='.db_input($userid).')';
+        }
+
+        if (($res=db_query($sql)) && db_num_rows($res))
+            $backends[] = db_result($res);
+
+        return array_filter($backends);
+    }
+
+    function login($user, $bk) {
+        global $ost;
+
+        if (!($user instanceof Staff))
+            return false;
+
+        // Ensure staff is allowed for realz to be authenticated via the backend.
+        if (!static::isBackendAllowed($user, $bk))
+            return false;
+
+        //Log debug info.
+        $ost->logDebug('Staff login',
+            sprintf("%s logged in [%s], via %s", $user->getUserName(),
+                $_SERVER['REMOTE_ADDR'], get_class($bk))); //Debug.
+
+        $sql='UPDATE '.STAFF_TABLE.' SET lastlogin=NOW() '
+            .' WHERE staff_id='.db_input($user->getId());
+        db_query($sql);
+        //Now set session crap and lets roll baby!
+        $_SESSION['_staff'] = array(); //clear.
+        $_SESSION['_staff']['userID'] = $user->getUserName();
+
+        $user->refreshSession(); //set the hash.
+
+        $_SESSION['TZ_OFFSET'] = $user->getTZoffset();
+        $_SESSION['TZ_DST'] = $user->observeDaylight();
+
+        //Regenerate session id.
+        $sid = session_id(); //Current id
+        session_regenerate_id(true);
+        // Destroy old session ID - needed for PHP version < 5.1.0
+        // DELME: remove when we move to php 5.3 as min. requirement.
+        if(($session=$ost->getSession()) && is_object($session)
+                && $sid!=session_id())
+            $session->destroy($sid);
+
+        Signal::send('auth.login.succeeded', $user);
+
+        $user->cancelResetTokens();
+
+        return true;
+    }
+}
+
+abstract class UserAuthenticationBackend  extends AuthenticationBackend {
+
+    static private $_registry = array();
+
+    static function _register($class) {
+        static::$_registry[$class::$id] = $class;
+    }
+
+    static function allRegistered() {
+        return array_merge(self::$_registry, parent::allRegistered());
+    }
+
+    function getAllowedBackends($userid) {
+        // White listing backends for specific user not supported.
+        return array();
+    }
+
+    function login($user, $bk) {
+        global $ost;
+
+        if (!($user instanceof TicketUser))
+            return false;
+
+        $_SESSION['_client'] = array(); //clear.
+        $_SESSION['_client']['userID'] = $user->getEmail(); //Email
+        //$_SESSION['_client']['key'] = $ticket->getExtId(); //Ticket ID --acts as password when used with email. See above.
+        $_SESSION['_client']['token'] = $user->getSessionToken();
+        $_SESSION['TZ_OFFSET'] = $ost->getConfig()->getTZoffset();
+        $_SESSION['TZ_DST'] = $ost->getConfig()->observeDaylightSaving();
+        $user->refreshSession(); //set the hash.
+        //Log login info...
+        $msg=sprintf('%s/%s logged in [%s]',
+                $user->getEmail(), $user->getId(), $_SERVER['REMOTE_ADDR']);
+        $ost->logDebug('User login', $msg);
+
+        //Regenerate session ID.
+        $sid=session_id(); //Current session id.
+        session_regenerate_id(TRUE); //get new ID.
+        if(($session=$ost->getSession()) && is_object($session) && $sid!=session_id())
+            $session->destroy($sid);
+
+        return true;
+    }
+
+}
+
 /**
  * This will be an exception in later versions of PHP
  */
@@ -287,8 +376,9 @@ class AuthLockoutBackend extends AuthenticationBackend {
 }
 AuthenticationBackend::register(AuthLockoutBackend);
 
-class osTicketAuthentication extends AuthenticationBackend {
-    static $name = "Local Authenication";
+
+class osTicketAuthentication extends StaffAuthenticationBackend {
+    static $name = "Local Authentication";
     static $id = "local";
 
     function authenticate($username, $password) {
@@ -306,5 +396,5 @@ class osTicketAuthentication extends AuthenticationBackend {
         }
     }
 }
-AuthenticationBackend::register(osTicketAuthentication);
+StaffAuthenticationBackend::register(osTicketAuthentication);
 ?>