Custome Auth Adapter

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Custome Auth Adapter

Troy Marker
I am trying to add Zend_Auth to my application. I use a database to hold
user information. Using the Digest Adapter include with Zend_Auth, I created
my own adapter.

The code for my adapter class is: (comments removed)

class TronPro_Auth_Adapter extends Zend_Auth_Adapter
{
    public function __construct()
    {
    }

    public static function staticAuthenticate(array $options)
    {
        $optionsRequired = array('username', 'password');
        $tokenData = array();
        foreach ($optionsRequired as $optionRequired) {
            if (!isset($options[$optionRequired]) ||
!is_string($options[$optionRequired])) {
                throw Zend::exception('TronPro_Auth_Exception', "Option
'$optionRequired' is required to be "
                                    . 'provided as a string');
            }
        }

        $id       = "{$options['username']}";
        $idLength = strlen($id);

        $tokenData['tokenValid']    = false;
        $tokenData['tokenIdentity'] = $options['username'];

        $db = Zend::registry('context')->db;
        $table = new TronPro_Model_Db_MembersTable();

    $where = $db->quoteInto('username = ?', $options['username'])
                .$db->quoteInto(' AND password = ?',
md5($options['password']))
                .$db->quoteInto(' AND active = ?', 'y');
        $row = $table->fetchRow($where);
        if ($row->username != '') {
        $tokenData['tokenValid'] = true;
        $tokenData['tokenUsername'] = $row->username;
        $tokenData['tokenEmail'] = $row->email;
        $tokenData['tokenLevel'] = $row->lev;
        $tokenData['tokenMessage'] = null;
        } else {
                        $tokenData['tokenMessage'] = 'Password incorrect';
        }
        return new TronPro_Auth_Token($tokenData);
    }

    public function authenticate(array $options)
    {
        return self::staticAuthenticate($options);
    }

}

My token class is:

require_once 'Zend/Auth/Token/Interface.php';

class TronPro_Auth_Token implements Zend_Auth_Token_Interface
{
    /**
     * Whether or not this token represents a successful authentication
attempt
     *
     * @var boolean
     */
    protected $_valid;

    /**
     * Array containing the username and realm from the authentication
attempt
     *
     * @var array
     */
    protected $_identity;

    /**
     * Message from the authentication adapter describing authentication
failure
     *
     * @var string|null
     */
    protected $_message;
    protected $_username;
    protected $_email;
    protected $_level;


    /**
     * Sets the token values, as appropriate
     *
     * @param  boolean $valid
     * @param  array   $identity
     * @param  string  $message
     * @return void
     */
    public function __construct($data)
    {
        $this->_valid    = $data['tokenValid'];
        $this->_identity = $data['tokenIdentity'];
        $this->_message  = $data['tokenMessage'];
        $this->_username = $data['tokenUsername'];
        $this->_email = $data['tokenEmail'];
        $this->_level = $data['tokenLevel'];

    }

    /**
     * Defined by Zend_Auth_Token_Interface
     *
     * @return boolean
     */
    public function isValid()
    {
        return $this->_valid;
    }
    /**
     * Defined by Zend_Auth_Token_Interface
     *
     * Returns an array having keys of 'realm' and 'username', having string
values that
     * correspond to those provided in the authentication request.
     *
     * @return array
     */
    public function getIdentity()
    {
        return $this->_identity;
    }
    /**
     * Defined by Zend_Auth_Token_Interface
     *
     * @return string|null
     */
    public function getMessage()
    {
        return $this->_message;
    }
        public function getUsername()
        {
                return $this->_username;
        }
        public function getEmail()
        {
                return $this->_email;
        }
        public function getLevel()
        {
                return $this->_level;
        }
}

Upon testing it, I get the following in my server error log:

[Sun Dec 17 19:53:47 2006] [error] [client 127.0.0.1] PHP Fatal error:
Uncaught exception 'Zend_Session_Exception' with message 'A session
namespace "Zend_Auth" already exists and has been set as the only instance
of this namespace.' in L:\\TronPro\\Lib\\Zend.php:229
Stack trace:
#0 L:\\TronPro\\Lib\\Zend\\Session.php(101):
Zend::exception('Zend_Session_Ex...', 'A session names...')
#1 L:\\TronPro\\Lib\\Zend\\Auth.php(107):
Zend_Session->__construct('Zend_Auth', true)
#2 L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(82):
Zend_Auth->authenticate(Array)
#3 [internal function]: IndexController->ProcessLogin(Array)
#4
L:\\TronPro\\Lib\\XAjax\\core\\plugin_layer\\xajaxDefaultRequestProcessorPlu
gin.inc.php(137): call_user_func_array(Array, Array)
#5 L:\\TronPro\\Lib\\XAjax\\core\\xajax.inc.php(544):
xajaxDefaultRequestProcessorPlugin->processRequest()
#6 L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(53):
xajax->processRequest()
#7 L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(18):
IndexController->showLogin()
#8 L:\\TronPro\\Lib\\Zend\\Controller\\Dispatcher.php(436): IndexCo in
L:\\TronPro\\Lib\\Zend.php on line 229, referer: http://net.tecg.org/

I am not sure why I am getting this error. If anyone could help me with this
I would greatly appreciate it.

Regards,
Troy L. Marker

Reply | Threaded
Open this post in threaded view
|

Re: Custome Auth Adapter

Darby Felton
Hi Troy,

Your code looks okay to me, though we may be missing some context
information that could be relevant to the problem. I think that the
problem lies in Zend_Auth's use of Zend_Session, which may or may not be
quite correct.

I have filed a bug report on your behalf in the JIRA issue tracker, as
this is something that we will need to fix:

http://framework.zend.com/issues/browse/ZF-657

Until we have resolved the use of Zend_Session within Zend_Auth, you may
work around this default behavior by not allowing Zend_Auth to use
Zend_Session. This is easy to do by passing false to the $useSession
parameter of the Zend_Auth constructor:

$auth = new Zend_Auth(new TronPro_Auth_Adapter(), false);

I've copied Gavin and Ralph, who maintain Zend_Session, in order to
garner support for fixing whatever problems may exist in Zend_Auth's use
of Zend_Session.

Thank you for the report!

Best regards,
Darby

Troy L. Marker wrote:

> I am trying to add Zend_Auth to my application. I use a database to hold
> user information. Using the Digest Adapter include with Zend_Auth, I created
> my own adapter.
>
> The code for my adapter class is: (comments removed)
>
> class TronPro_Auth_Adapter extends Zend_Auth_Adapter
> {
>     public function __construct()
>     {
>     }
>
>     public static function staticAuthenticate(array $options)
>     {
>         $optionsRequired = array('username', 'password');
>         $tokenData = array();
>         foreach ($optionsRequired as $optionRequired) {
>             if (!isset($options[$optionRequired]) ||
> !is_string($options[$optionRequired])) {
>                 throw Zend::exception('TronPro_Auth_Exception', "Option
> '$optionRequired' is required to be "
>                                     . 'provided as a string');
>             }
>         }
>
>         $id       = "{$options['username']}";
>         $idLength = strlen($id);
>
>         $tokenData['tokenValid']    = false;
>         $tokenData['tokenIdentity'] = $options['username'];
>
>         $db = Zend::registry('context')->db;
>         $table = new TronPro_Model_Db_MembersTable();
>
>     $where = $db->quoteInto('username = ?', $options['username'])
>                 .$db->quoteInto(' AND password = ?',
> md5($options['password']))
>                 .$db->quoteInto(' AND active = ?', 'y');
>         $row = $table->fetchRow($where);
>         if ($row->username != '') {
>         $tokenData['tokenValid'] = true;
>         $tokenData['tokenUsername'] = $row->username;
>         $tokenData['tokenEmail'] = $row->email;
>         $tokenData['tokenLevel'] = $row->lev;
>         $tokenData['tokenMessage'] = null;
>         } else {
> $tokenData['tokenMessage'] = 'Password incorrect';
>         }
>         return new TronPro_Auth_Token($tokenData);
>     }
>
>     public function authenticate(array $options)
>     {
>         return self::staticAuthenticate($options);
>     }
>
> }
>
> My token class is:
>
> require_once 'Zend/Auth/Token/Interface.php';
>
> class TronPro_Auth_Token implements Zend_Auth_Token_Interface
> {
>     /**
>      * Whether or not this token represents a successful authentication
> attempt
>      *
>      * @var boolean
>      */
>     protected $_valid;
>
>     /**
>      * Array containing the username and realm from the authentication
> attempt
>      *
>      * @var array
>      */
>     protected $_identity;
>
>     /**
>      * Message from the authentication adapter describing authentication
> failure
>      *
>      * @var string|null
>      */
>     protected $_message;
>     protected $_username;
>     protected $_email;
>     protected $_level;
>
>
>     /**
>      * Sets the token values, as appropriate
>      *
>      * @param  boolean $valid
>      * @param  array   $identity
>      * @param  string  $message
>      * @return void
>      */
>     public function __construct($data)
>     {
>         $this->_valid    = $data['tokenValid'];
>         $this->_identity = $data['tokenIdentity'];
>         $this->_message  = $data['tokenMessage'];
>         $this->_username = $data['tokenUsername'];
>         $this->_email = $data['tokenEmail'];
>         $this->_level = $data['tokenLevel'];
>
>     }
>
>     /**
>      * Defined by Zend_Auth_Token_Interface
>      *
>      * @return boolean
>      */
>     public function isValid()
>     {
>         return $this->_valid;
>     }
>     /**
>      * Defined by Zend_Auth_Token_Interface
>      *
>      * Returns an array having keys of 'realm' and 'username', having string
> values that
>      * correspond to those provided in the authentication request.
>      *
>      * @return array
>      */
>     public function getIdentity()
>     {
>         return $this->_identity;
>     }
>     /**
>      * Defined by Zend_Auth_Token_Interface
>      *
>      * @return string|null
>      */
>     public function getMessage()
>     {
>         return $this->_message;
>     }
> public function getUsername()
> {
> return $this->_username;
> }
> public function getEmail()
> {
> return $this->_email;
> }
> public function getLevel()
> {
> return $this->_level;
> }
> }
>
> Upon testing it, I get the following in my server error log:
>
> [Sun Dec 17 19:53:47 2006] [error] [client 127.0.0.1] PHP Fatal error:
> Uncaught exception 'Zend_Session_Exception' with message 'A session
> namespace "Zend_Auth" already exists and has been set as the only instance
> of this namespace.' in L:\\TronPro\\Lib\\Zend.php:229
> Stack trace:
> #0 L:\\TronPro\\Lib\\Zend\\Session.php(101):
> Zend::exception('Zend_Session_Ex...', 'A session names...')
> #1 L:\\TronPro\\Lib\\Zend\\Auth.php(107):
> Zend_Session->__construct('Zend_Auth', true)
> #2 L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(82):
> Zend_Auth->authenticate(Array)
> #3 [internal function]: IndexController->ProcessLogin(Array)
> #4
> L:\\TronPro\\Lib\\XAjax\\core\\plugin_layer\\xajaxDefaultRequestProcessorPlu
> gin.inc.php(137): call_user_func_array(Array, Array)
> #5 L:\\TronPro\\Lib\\XAjax\\core\\xajax.inc.php(544):
> xajaxDefaultRequestProcessorPlugin->processRequest()
> #6 L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(53):
> xajax->processRequest()
> #7 L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(18):
> IndexController->showLogin()
> #8 L:\\TronPro\\Lib\\Zend\\Controller\\Dispatcher.php(436): IndexCo in
> L:\\TronPro\\Lib\\Zend.php on line 229, referer: http://net.tecg.org/
>
> I am not sure why I am getting this error. If anyone could help me with this
> I would greatly appreciate it.
>
> Regards,
> Troy L. Marker
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Custome Auth Adapter

Troy Marker
I am not sure it if this is relevent to the problem, but
the context in which I am a using Zend_Auth is:

My Bootstrap creates an application context class that
contains all the configutration.

In the application context class I have the following
lines:

$this->auth = $auth = new Zend_Auth(new
TronPro_Auth_Adaptor);
Zend::register('auth', $auth);

This way when ever I need to call the auth class in my
controllers, I call the auth class stored in the registry.

For instance, to authenticate a user I use:

$option = array('username'=>$aFormVals['username'],
'password' => $aFormVals['password']);
$token = Zend::registry('auth')->authenticate($option);

And to check for a valid token is use:

Zend::registry('auth')->isLoggedIn();

I hope that helps with the problem. I should have include
it before.

also, forgive any typing mistakes, I am at work and am
type this for memory. I sure miss Cut-And-Paste!!

Regards,
Troy L. Marker.

On Mon, 18 Dec 2006 11:18:16 -0500
  Darby Felton <[hidden email]> wrote:

> Hi Troy,
>
> Your code looks okay to me, though we may be missing
>some context
> information that could be relevant to the problem. I
>think that the
> problem lies in Zend_Auth's use of Zend_Session, which
>may or may not be
> quite correct.
>
> I have filed a bug report on your behalf in the JIRA
>issue tracker, as
> this is something that we will need to fix:
>
> http://framework.zend.com/issues/browse/ZF-657
>
> Until we have resolved the use of Zend_Session within
>Zend_Auth, you may
> work around this default behavior by not allowing
>Zend_Auth to use
> Zend_Session. This is easy to do by passing false to the
>$useSession
> parameter of the Zend_Auth constructor:
>
> $auth = new Zend_Auth(new TronPro_Auth_Adapter(),
>false);
>
> I've copied Gavin and Ralph, who maintain Zend_Session,
>in order to
> garner support for fixing whatever problems may exist in
>Zend_Auth's use
> of Zend_Session.
>
> Thank you for the report!
>
> Best regards,
> Darby
>
> Troy L. Marker wrote:
>> I am trying to add Zend_Auth to my application. I use a
>>database to hold
>> user information. Using the Digest Adapter include with
>>Zend_Auth, I created
>> my own adapter.
>>
>> The code for my adapter class is: (comments removed)
>>
>> class TronPro_Auth_Adapter extends Zend_Auth_Adapter
>> {
>>     public function __construct()
>>     {
>>     }
>>
>>     public static function staticAuthenticate(array
>>$options)
>>     {
>>         $optionsRequired = array('username',
>>'password');
>>         $tokenData = array();
>>         foreach ($optionsRequired as $optionRequired) {
>>             if (!isset($options[$optionRequired]) ||
>> !is_string($options[$optionRequired])) {
>>                 throw
>>Zend::exception('TronPro_Auth_Exception', "Option
>> '$optionRequired' is required to be "
>>                                     . 'provided as a
>>string');
>>             }
>>         }
>>
>>         $id       = "{$options['username']}";
>>         $idLength = strlen($id);
>>
>>         $tokenData['tokenValid']    = false;
>>         $tokenData['tokenIdentity'] =
>>$options['username'];
>>
>>         $db = Zend::registry('context')->db;
>>         $table = new TronPro_Model_Db_MembersTable();
>>
>>     $where = $db->quoteInto('username = ?',
>>$options['username'])
>>                 .$db->quoteInto(' AND password = ?',
>> md5($options['password']))
>>                 .$db->quoteInto(' AND active = ?', 'y');
>>         $row = $table->fetchRow($where);
>>         if ($row->username != '') {
>>         $tokenData['tokenValid'] = true;
>>         $tokenData['tokenUsername'] = $row->username;
>>         $tokenData['tokenEmail'] = $row->email;
>>         $tokenData['tokenLevel'] = $row->lev;
>>         $tokenData['tokenMessage'] = null;
>>         } else {
>> $tokenData['tokenMessage'] = 'Password incorrect';
>>         }
>>         return new TronPro_Auth_Token($tokenData);
>>     }
>>
>>     public function authenticate(array $options)
>>     {
>>         return self::staticAuthenticate($options);
>>     }
>>
>> }
>>
>> My token class is:
>>
>> require_once 'Zend/Auth/Token/Interface.php';
>>
>> class TronPro_Auth_Token implements
>>Zend_Auth_Token_Interface
>> {
>>     /**
>>      * Whether or not this token represents a successful
>>authentication
>> attempt
>>      *
>>      * @var boolean
>>      */
>>     protected $_valid;
>>
>>     /**
>>      * Array containing the username and realm from the
>>authentication
>> attempt
>>      *
>>      * @var array
>>      */
>>     protected $_identity;
>>
>>     /**
>>      * Message from the authentication adapter
>>describing authentication
>> failure
>>      *
>>      * @var string|null
>>      */
>>     protected $_message;
>>     protected $_username;
>>     protected $_email;
>>     protected $_level;
>>
>>
>>     /**
>>      * Sets the token values, as appropriate
>>      *
>>      * @param  boolean $valid
>>      * @param  array   $identity
>>      * @param  string  $message
>>      * @return void
>>      */
>>     public function __construct($data)
>>     {
>>         $this->_valid    = $data['tokenValid'];
>>         $this->_identity = $data['tokenIdentity'];
>>         $this->_message  = $data['tokenMessage'];
>>         $this->_username = $data['tokenUsername'];
>>         $this->_email = $data['tokenEmail'];
>>         $this->_level = $data['tokenLevel'];
>>
>>     }
>>
>>     /**
>>      * Defined by Zend_Auth_Token_Interface
>>      *
>>      * @return boolean
>>      */
>>     public function isValid()
>>     {
>>         return $this->_valid;
>>     }
>>     /**
>>      * Defined by Zend_Auth_Token_Interface
>>      *
>>      * Returns an array having keys of 'realm' and
>>'username', having string
>> values that
>>      * correspond to those provided in the
>>authentication request.
>>      *
>>      * @return array
>>      */
>>     public function getIdentity()
>>     {
>>         return $this->_identity;
>>     }
>>     /**
>>      * Defined by Zend_Auth_Token_Interface
>>      *
>>      * @return string|null
>>      */
>>     public function getMessage()
>>     {
>>         return $this->_message;
>>     }
>> public function getUsername()
>> {
>> return $this->_username;
>> }
>> public function getEmail()
>> {
>> return $this->_email;
>> }
>> public function getLevel()
>> {
>> return $this->_level;
>> }
>> }
>>
>> Upon testing it, I get the following in my server error
>>log:
>>
>> [Sun Dec 17 19:53:47 2006] [error] [client 127.0.0.1]
>>PHP Fatal error:
>> Uncaught exception 'Zend_Session_Exception' with message
>>'A session
>> namespace "Zend_Auth" already exists and has been set as
>>the only instance
>> of this namespace.' in L:\\TronPro\\Lib\\Zend.php:229
>> Stack trace:
>> #0 L:\\TronPro\\Lib\\Zend\\Session.php(101):
>> Zend::exception('Zend_Session_Ex...', 'A session
>>names...')
>> #1 L:\\TronPro\\Lib\\Zend\\Auth.php(107):
>> Zend_Session->__construct('Zend_Auth', true)
>> #2
>>L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(82):
>> Zend_Auth->authenticate(Array)
>> #3 [internal function]:
>>IndexController->ProcessLogin(Array)
>> #4
>> L:\\TronPro\\Lib\\XAjax\\core\\plugin_layer\\xajaxDefaultRequestProcessorPlu
>> gin.inc.php(137): call_user_func_array(Array, Array)
>> #5 L:\\TronPro\\Lib\\XAjax\\core\\xajax.inc.php(544):
>> xajaxDefaultRequestProcessorPlugin->processRequest()
>> #6
>>L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(53):
>> xajax->processRequest()
>> #7
>>L:\\TronPro\\Apps\\TronProNet\\Controller\\IndexController.php(18):
>> IndexController->showLogin()
>> #8
>>L:\\TronPro\\Lib\\Zend\\Controller\\Dispatcher.php(436):
>>IndexCo in
>> L:\\TronPro\\Lib\\Zend.php on line 229, referer:
>>http://net.tecg.org/
>>
>> I am not sure why I am getting this error. If anyone
>>could help me with this
>> I would greatly appreciate it.
>>
>> Regards,
>> Troy L. Marker
>>
>>

Reply | Threaded
Open this post in threaded view
|

Saveing Zend_Auth tokens

Troy Marker
After working with Zend_Auth, I have came up with a couple questions.

I got my previous problem working by turning off Zend_Session use in
Zend_Auth. While this did fix one problem, it presented another. Without
using Zend_Session, how can we save the state if the authentication? What
happened to me is this:

I was able to login using my login in form. However, after login I tried to
use the isLoggedIn method, and go the same Session error I received in my
other attempts.

I do have the following suggestions:

1) If the sessions are turned off, make the other methods in the class aware
of it, and possibly throw an exception indicating that sessions are
disabled.

2) Perhaps change Zend_Auth to allow for other state saving mechanisms. For
instance, take the session functions out of Zend_Auth, and create an adapter
to save the token data. This will allow using sessions, databases, or evem
files to save the token information.

I am not sure it theses suggestions are possible, they are just my ideas.

Regards,
Troy L. Marker



Reply | Threaded
Open this post in threaded view
|

RE: Saveing Zend_Auth tokens

Troy Marker
Okay, sorry, I posted before I thought.

I was sitting here thinking about my idea, and figured out that no matter
how you save the token data, you will need a session variable to be able to
track the token across pages.

Sorry for wasting peoples time.

Regards,
Troy L. Marker

-----Original Message-----
From: Troy L. Marker [mailto:[hidden email]]
Sent: Monday, December 18, 2006 10:28 PM
To: [hidden email]
Subject: [fw-auth] Saveing Zend_Auth tokens


After working with Zend_Auth, I have came up with a couple questions.

I got my previous problem working by turning off Zend_Session use in
Zend_Auth. While this did fix one problem, it presented another. Without
using Zend_Session, how can we save the state if the authentication? What
happened to me is this:

I was able to login using my login in form. However, after login I tried to
use the isLoggedIn method, and go the same Session error I received in my
other attempts.

I do have the following suggestions:

1) If the sessions are turned off, make the other methods in the class aware
of it, and possibly throw an exception indicating that sessions are
disabled.

2) Perhaps change Zend_Auth to allow for other state saving mechanisms. For
instance, take the session functions out of Zend_Auth, and create an adapter
to save the token data. This will allow using sessions, databases, or evem
files to save the token information.

I am not sure it theses suggestions are possible, they are just my ideas.

Regards,
Troy L. Marker





--
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.1.409 / Virus Database: 268.15.24/592 - Release Date: 12/18/2006