In a ZF2 project i am using the AuthenticationService to validate a users log in credentials. This is working fine, except it only stores in the session a string containing the users name.
What i would like would be for subsequent calls to AuthenticationService::getIdentity to return a custom Identity object, that is populated with the users database id, roles and permissions (popualted from an RBAC service), so that the object in the session is a bit more useful.
I am able to create this object, but am unsure of the best way to keep it in the session; ideally i would like to override the entry with the key Zend_Auth, but this does not seem to be working.
My code so far:
<?php
namespace Authentication\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Authentication\AuthenticationService;
use Authentication\Form\Login\LoginForm;
use Zend\Form\Form;
use Authentication\Model\Identity\AuthenticatedIdentity;
class AuthenticationController extends AbstractActionController
{
/**
*
* @var AuthenticationService
*/
protected $authenticationService;
/**
*
* @var LoginForm
*/
protected $loginForm;
/**
*
* @param AuthenticationService $authenticationService
* @param LoginForm $loginForm
*/
public function __construct(AuthenticationService $authenticationService, LoginForm $loginForm){
$this->authenticationService = $authenticationService;
$this->loginForm = $loginForm;
}
public function indexAction(){
$form = $this->loginForm;
$viewModel = new ViewModel();
$viewModel->setVariables([
'loginForm' => $form
]);
if($this->getRequest()->isPost() === false){
return $viewModel;
}
$form->setData($this->getRequest()->getPost());
if($form->isValid() === false){
return $viewModel;
}
$data = $form->getData();
$authenticationAdapter = $this->authenticationService->getAdapter();
$authenticationAdapter->setIdentity($data['credentials']['username'])
->setCredential($data['credentials']['password']);
$authenticationResult = $this->authenticationService->authenticate($authenticationAdapter);
if($authenticationResult->isValid() === false){
$viewModel->setVariable('validCredentials', false);
return $viewModel;
}
/**
* Create a user model and save it to the session.
*/
$authenticationResultRow = $authenticationAdapter->getResultRowObject(null, ['password']);
$permissions = $this->rbacService->getPermissionsForUser($authenticationResultRow->user_id);
$roles = $this->rbacService->getRolesForUser($authenticationResultRow->user_id);
$identity = new AuthenticatedIdentity(
$authenticationResult->getIdentity(),
'admin',
$permissions,
$roles
);
$identity->setUserId($authenticationResultRow->user_id);
//how to store this Identity object in session so AuthenticationService will return it?
return $this->redirect()->toRoute('dashboard');
}
}
Check out https://github.com/zendframework/zend-authentication/blob/master/src/AuthenticationService.php#L75 and https://github.com/zendframework/zend-authentication/blob/master/src/Storage/StorageInterface.php
You can write the AuthenticatedIdentity
object directly to the storage like so:
$this->authenticationService->getStorage()->write($identity);
However, I would advice against doing so because:
AuthenticatedIdentity
object and all objects it contains need to be serializable, which can become problematic to maintain.I would (and do) fetch the user object and/or roles when needed, either from DB or some form of cache but don't store it in the session.