Authentication service

This is a followup to my previous post “ZF Authentication using Doctrine“. After posting my implementation of using a ZendX doctrine auth adapter. I got some feedback from Jon Lebensold from ZendCasts. The issue raised is that my implementation makes the controller fat, which is considered as a bad practice. I cannot agree more on that. So … I tried to refactor the code and come up with the introduction of a service layer class named “AuthenticationService”.

Now the LoginController class is made thinner with the following code.

public function loginAction()
{
    $authService = new Model_AuthenticationService();
    if($authService->isAuthenticated() == true) {
        $this->_redirect('/index');
    }

    if($this->getRequest()->isPost()) {
        $this->view->headTitle('Login');
        // collect the data from the user
        $loginUsername = $this->getRequest()->getParam('username', '');
        $loginPassword = $this->getRequest()->getParam('password', '');

        $authResult = $authService->authenticate(
            $loginUsername,
            $loginPassword
        );

        if($authResult == true) {
            // auth good, do your logic
        }
        else {
            // auth bad, do your logic
        }
    } else {
        $this->_redirect('/login');
    }
}

Code for AuthenticationService.php

class Model_AuthenticationService
{
    private $_authenticationMessage = '';

    public function getAuthenticationMessage()
    {
        return $this->_authenticationMessage;
    }

    public function isAuthenticated()
    {
        return Zend_Auth::getInstance()->hasIdentity();
    }

    public function authenticate($username, $password)
    {
        $doctrineAuthAdapter = new ZendX_Doctrine_Auth_Adapter(
            Doctrine_core::getConnectionByTableName('Model_User')
        );
        $doctrineAuthAdapter->setTableName('Model_User u')
            ->setIdentityColumn('u.username')
            ->setCredentialColumn('u.password')
            ->setIdentity($username)
            ->setCredential(Model_Utility::encryptPassword($password));

        $myAuth = Zend_Auth::getInstance();
        $authResult = $myAuth->authenticate($doctrineAuthAdapter);
        if(!$authResult->isValid()) {
            $this->_authenticationMessage = 'You have entered invalid username and password.';
            return false;
        } else {
            $identity = $doctrineAuthAdapter->getResultRowObject(null, 'password');
            $myAuth->getStorage()->write($identity);
            return true;
        }
    }
}

As we can see, the AuthenticationService class is now doing most of the heavy lifting stuff. The controller is left with the duty of checking user login state and dispatching appropriate actions when necessary.

Hope this makes sense, and again more than happy to discuss.

Reference

Share this article on:
  • Facebook
  • Twitter
  • Google Bookmarks
  • Digg
  • del.icio.us
  • LinkedIn
  • MySpace
  • email
  • Live
  • Reddit
  • RSS
  • StumbleUpon

Related posts:

  1. ZF authentication using Doctrine
  2. Application logging with Zend_Log
  3. Common library files organization in ZF
  4. ZF, Doctrine and Unit Tests
  5. Zend Framework 1 and Doctrine 2 integration
Categories: Doctrine - PHP - Zend Framework
Martín
Hi @jim, I like this more, I used a similar approach but I forgot to include the authentication control in my Model :) I saw that you have the same problem with Jon’s approach of Zend_Auth, I see that you are using $myAuth->getStorage()->write($identity); to grab the identity in Zend_Auth, if I understood well @jon said that Zend_Auth make this automatically in his implementation but apparently not. I try to grab the identity in Zend_Auth to persist data but without success, did you try ? Greetings
3 February 10 at 00:19
@Martín the solution from ZendCasts does do the storage write. Zend_Auth::getInstance() returns an instance of Zend_Arth, if you have a look at the authenticate() method under that class, you’ll find it’s writing the identity to the default storage.

I did try to run the code form ZendCasts, it’s not persisting the user identity for me too. But I think it must be an issue to do with the Doctrine setup (I didn’t have time to look into it deep).

The reason why I’m favouring using the ZendX lib is explained in my reply to your comment on the other post.
3 February 10 at 00:38
ah! have a look on ZendCasts, @dave found out the issue.
3 February 10 at 00:40
Martín
Hi, yes I saw what @dave found, I will try tomorrow. Greetings and thank you.
3 February 10 at 08:23
Martín
Hi @jim, I probe what @dave found and everything is ok, the problem was in that line. Thank you !!!
4 February 10 at 02:59
 
[...] Authentication service [...]