Zend_Auth and Zend_Session_Namespace... Please Review.

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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.
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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.)
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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.
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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(); ??
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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?
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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:
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post by pickle »

Moved to "Coding Critique" forum.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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/
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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).
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend_Auth and Zend_Session_Namespace... Please Review.

Post 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!
Post Reply