Palo Verde

Web Application Developer

Zend_Auth adapter with Doctrine

Here is an example of a Zend_Auth adapter for the Zend Framework that uses Doctrine as the ORM.

<?php
/**
 * Zend_Auth adapter for an extended Doctrine users record.
 *
 *@package PaloVerde
 *@author Sam McCallum <sam@palo-verde.us>
 */
class PaloVerde_Auth implements Zend_Auth_Adapter_Interface {
    public $username;
    public $password;
    public $user;
    
    const NOT_FOUND_MESSAGE = "The username you entered could not be found.";
    const CREDINTIALS_MESSAGE = "The password you entered is not correct.";
    const UNKNOWN_FAILURE = "Authentication failed for an unknown reason.";
    
    public function __construct($username, $password) {
        $this->username = $username;
        $this->password = $password;
    }
    
    /** 
     * Zend_Auth hook.
     */
    public function authenticate() {
        try {
            $this->user = Users::authenticate($this->username, $this->password);
        } catch (Exception $e) {
            if ($e->getMessage() == Users::NOT_FOUND) {
                return $this->notFound();
            }
            
            if ($e->getMessage() == Users::PASSWORD_MISMATCH) {
                return $this->passwordMismatch();
            }
            
            return $this->failed($e);
        }
        
        return $this->success();
    }
    
    /**
     * Factory for Zend_Auth_Result
     *
     *@param integer    The Result code, see Zend_Auth_Result
     *@param mixed      The Message, can be a string or array
     *@return Zend_Auth_Result
     */
    public function result($code, $messages = array()) {
        if (!is_array($messages)) {
            $messages = array($messages);
        }
        
        return new Zend_Auth_Result(
            $code,
            $this->username,
            $messages
        );
    }
    
    /**
     * "User not found" wrapper for $this->result()
     */
    public function notFound() {
        return $this->result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND,self::NOT_FOUND_MESSAGE);
    }
    
    /**
     * "Password does not match" wrapper for $this->result()
     */
    public function passwordMismatch() {
        return $this->result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND,self::CREDINTIALS_MESSAGE);
    }
    
    /**
     * General or Unknown failure wrapper for $this->result()
     */
    public function failed(Exception $e) {
        return $this->result(Zend_Auth_Result::FAILURE, self::UNKNOWN_FAILURE);
    }
    
    /**
     * "Success" wrapper for $this->result()
     */
    public function success() {
        return $this->result(Zend_Auth_Result::SUCCESS);
    }
}
?>

So... basically we call a method on the model Users::authenticate(username, password), which returns a valid user object on success or throws and exception on fail, we catch the exceptions or success and wrap then in the Zend_Auth_Result container, and pass it on.

Here is the Doctrine Record

<?php
class Users extends Doctrine_Record {
    const NOT_FOUND = 1;
    const PASSWORD_MISMATCH = 2;
    
    public function setTableDefinition() {
        $this->hasColumn('name','text', array('unique', 'notblank','nospace'));
        $this->hasColumn('pass','text', array('notblank','nospace'));
        $this->hasColumn('email','text', array('email','notblank','nospace'));
    }

    public static function authenticate($username, $password) {
        $md5_pass = md5($password);
        $theUser = Doctrine::getTable('Users')->findOneByName($username);
        
        if (!$theUser) {
            throw new Exception(self::NOT_FOUND);
        }
        
        if ($theUser->pass != $md5_pass) {
            throw new Exception(self::PASSWORD_MISMATCH);
        }

        return $theUser->toArray();
    }
}
?>

That should be pretty self explanatory if you are used to Doctrine. We try an get a user with the passed username. If they exist and the password matches, then return it, otherwise throw the correct exception.

2 comments

  1. Hi, I have a problem with this, Zend_Auth generate an instance after I complete data to login but when I change or redirect to another page the instance seems to loose and I get an error of Zend_Session::start() when I try to to know if Zend_Auth::getInstance()->hasIdentity() If I do a var_dump(Zend_Auth::getInstance()); I get object(Zend_Auth)#56 (1) { ["_storage:protected"]=> NULL } How can I accomplish to persist data in every request ? Thank you

    — martin Fri, 29 Jan 2010

  2. Thanks for the example, I modified it some to fit my application but your implementation was exactly what I needed. Many thanks.

    — ahmad Sun, 27 Sep 2009

Please insert the result of the arithmetical operation from the following image:

Please insert the result of the arithmetical operation from this image. =