Page 1 of 1

Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Fri Jun 18, 2010 2:18 pm
by DaveTheAve
So this code, feels like it works, but I'd like your input... perhaps it doesn't and I'm just messing with my own head... who knows... Anyways, if it looks fine, if you have any input on how to make it better please let me know... if it doesn't work like I obviously intended it to do, please help me fix it.

Bootstrap.php:

Code: Select all

...
    protected function _initSessionHelper()
    {  
    	Zend_Session::start();
    	$sess = new Zend_Session_Namespace('Default');
    	$auth = Zend_Auth::getInstance();
    	
    	if($sess->user && !Zend_Auth::getInstance()->hasIdentity())
    	{
			$authStorage = $auth->getStorage();
            $authStorage->write($sess->user);
    	}
    }
...
UserController.php:

Code: Select all

...
    public function signinAction()
    {
        if(Zend_Auth::getInstance()->hasIdentity()){
            $this->_redirect('/');
        }
        
        $request = $this->getRequest();
        $form = new Application_Form_Signin();
        if($request->isPost()){
            if($form->isValid($this->_request->getPost())) {
                $username = $form->getValue('username');
                $password = $form->getValue('password');
                
                $authAdapter = new Application_Auth_Adapter($username,$password);
                
                $auth = Zend_Auth::getInstance();
                $result = $auth->authenticate($authAdapter);
                
                if($result->isValid()){
                	$user =  $this->_usersMapper->findByUsername($username,new Application_Model_Users());
                	
                	$sess = new Zend_Session_Namespace('Default');
                	$sess->user = $user;
                	Zend_Session::rememberMe(604800); // Week
                	
                    $authStorage = $auth->getStorage();
                    $authStorage->write($user);
                    
                    $this->_redirect('/');
                } else {
                    $this->view->errorMessage = "User name or password is wrong.";
                }
            }
        }
        
        $this->view->form = $form;   
    }
...
    public function signoutAction()
    {
        Zend_Auth::getInstance()->clearIdentity();
		Zend_Session::forgetMe();
		Zend_Session::destroy(true);
        $this->_redirect('/');
    }
...
Yes, I've googled, couldn't find any information on this topic... so weird too...

All i'm trying to do is keep the user logged in for a week and not get lost every time he navigates away from the page like normal Zend_Auth does.

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Fri Jun 18, 2010 3:11 pm
by Eran
I'm not sure why are you writing to the authStorage in the bootstrap if the user is not logged in - it doesn't make sense. Anyway as to your problem - make sure gc_maxlifetime is set to at least what you are trying to keep the user alive for (the default is 1440 seconds).
http://www.php.net/manual/en/session.co ... axlifetime

Also, you have to call the rememberMe() function before you write the session

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Fri Jun 18, 2010 4:46 pm
by DaveTheAve
So like this?

UserController.php:

Code: Select all

...
    public function signinAction()
    {
        if(Zend_Auth::getInstance()->hasIdentity()){
            $this->_redirect('/');
        }
        
        $request = $this->getRequest();
        $form = new Application_Form_Signin();
        if($request->isPost()){
            if($form->isValid($this->_request->getPost())) {
                $username = $form->getValue('username');
                $password = $form->getValue('password');
                
                $authAdapter = new Application_Auth_Adapter($username,$password);
                
                $auth = Zend_Auth::getInstance();
                $result = $auth->authenticate($authAdapter);
                
                if($result->isValid()){
                	$user =  $this->_usersMapper->findByUsername($username,new Application_Model_Users());

                	Zend_Session::rememberMe(604800); // Week
                	$sess = new Zend_Session_Namespace('Default');
                	$sess->user = $user;
                	
                    $authStorage = $auth->getStorage();
                    $authStorage->write($user);
                    
                    $this->_redirect('/');
                } else {
                    $this->view->errorMessage = "User name or password is wrong.";
                }
            }
        }
        
        $this->view->form = $form;   
    }
...
    public function signoutAction()
    {
        Zend_Auth::getInstance()->clearIdentity();
		Zend_Session::forgetMe();
		Zend_Session::destroy(true);
        $this->_redirect('/');
    }
...
Also, I'm writing to the Auth Storage because the rest of the site uses Zend_Auth::getInstance()->hasIdentity() to determine weather to display the page or a login screen.

The gc-maxlifetime.... that won't work for my case because the next step I need to do is make it so that the timeout is extended by a week for each time they visit the page. (Thus session will never expire if they use the site at-least once a week; and they will always be logged in.)

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Fri Jun 18, 2010 5:25 pm
by Eran
So like this?
yes
The gc-maxlifetime.... that won't work for my case because the next step I need to do is make it so that the timeout is extended by a week for each time they visit the page. (Thus session will never expire if they use the site at-least once a week; and they will always be logged in.)
You have to change it, otherwise your sessions will expire after 1440 seconds, no matter what. You can recreate the session for user on each visit to avoid it ever expiring, but if he comes back later than the time set in maxlifetime, he will be logged out (his session would've expired).

You might not notice it on your local development machine, since garbage collection of sessions takes place at random depending on gc_probability and gc_dividor - but on a live server with plenty of users, sessions will be destroyed almost exactly at the time specified by gc_maxlifetime.

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Fri Jun 18, 2010 8:19 pm
by DaveTheAve
So a quick ini_set("session.gc_maxlifetime", "604800"); in public.php will fix that issue right? (For a week)

Also, how do I - if I use: $sess = new Zend_Session_Namespace(); in the bootstrap - can I get that same namespace in the UserController.php without loading another $sess = new Zend_Session_Namespace();? Perhaps if I use a false function name you'd understand better, so something like this: $sess = Zend_Session::getSession(); ??

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Sat Jun 19, 2010 8:49 am
by Eran
So a quick ini_set("session.gc_maxlifetime", "604800"); in public.php will fix that issue right? (For a week)
yes. you should notice though, that it has to be called for any application running on the same server - since cookies will recycled based on the lowest maxlifetime (read the manual for more details).
Also, how do I - if I use: $sess = new Zend_Session_Namespace(); in the bootstrap - can I get that same namespace in the UserController.php without loading another $sess = new Zend_Session_Namespace();? Perhaps if I use a false function name you'd understand better, so something like this: $sess = Zend_Session::getSession();
What's the problem with creating another object for the same namespace?

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Sat Jun 19, 2010 7:37 pm
by DaveTheAve
Found a site to help me do what I'm looking for with Cookies... I won't post the link here because it does NOT meet my certain level of security.

I will post it here once I develop and implement it with multiple database tokens; similar to that stated here: http://jaspan.com/improved_persistent_l ... t_practice Though, mine will be even more secure than that.

Will also post it on my development blog, once I actually have one. :roll: I've had to research so many things that most people will come across that is not explained in the ZF documents and many other guides ether don't cover, or are outdated. :offtopic:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Mon Jun 21, 2010 9:59 am
by pickle
Moved to "Coding Critique" forum.

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Wed Jul 14, 2010 2:35 pm
by DaveTheAve
So I finally got the blog post done reguarding this topic and Zend_Auth.

You can view it here: http://www.devzone.neoeliteconsulting.c ... framework/

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Wed Jul 14, 2010 3:44 pm
by Weirdan
Couple of notes:
  1. running unserialize() on user-supplied data is a BIG no-no. If your cookie encryption/signing is compromised user will be able to execute destructors of any class you have available in your script, with a object variables being controlled by an attacker. See this advisory for example.
  2. time().mt_rand() gives worse entropy than simply mt_rand()
  3. those three tokens are generated and manipulated in the same way, so they are no better than a single token. The important thing you missed from the post you referenced is that one token is changed while the second is not, so invalid-valid combination can be used to detect data theft.
  4. there doesn't seem to be any differentiation between user logged via regular session cookie and your 'remember me' cookie (assuming you wanted to implement 'remember me' functionality like discussed in the post you reference).

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Posted: Wed Jul 14, 2010 3:59 pm
by DaveTheAve
Yeah I knew something you mentioned wouldn't be implemented in the code but it fix the need at the time. The next version will have the changes, as far as unserialize... I never knew that!