Question

I set up a Zend_Acl and Zend_Auth scheme where user is authenticated using Zend_Auth_Adapter_Ldap and stored in session. I use a controller plugin to check if $auth->hasIdentity() and $acl->isAllowed() to display login form if needed.

What I want to do is to add login cookies (my implementation of best practices), and API keys in addition to the session check in Zend_Auth. I also need to switch the role to 'owner', on content created by the user.

My concerns:

  • Login cookie should only be used as fallback if regular session auth fails, and thus the session should be authenticated
  • API keys should be used as fallback if both login cookie and session cookie fails
  • I don't want to store the password anywhere, it should only reside in LDAP
  • I need persistent storage of the identity, as looking it up in LDAP is not possible without full username and password
  • The role is dependent both on LDAP group membership (which needs to be persistently stored), and if the identity should be considered owner of the content (meaning it's changing in between requests, unless admin)

What's a good pattern / approach to solve this using Zend Framework MVC and Zend_Auth + Zend_Acl ?

Was it helpful?

Solution

you can create your own adapter/storage classes, with implementing Zend_Auth_Adpater_Interface and Zend_Auth_Storage_Interface

In these classes, you can re-use original adapters (like LDAP) or storages, and only write the code that implements your auth rules.

for example, using multiple sources for the Zend_Auth_Adapter :

<?php 
class My_Auth_Adapter implements Zend_Auth_Adapter_Interface
{
    private $ldapAdapter;
    private $cookieAdapter;
    private $apiKeyAdapter;

    public function __construct($ldapAdapter, $cookieAdapter, $apiKeyAdapter) {
    {
        $this->ldapAdapter = $ldapAdapter;
        $this->cookieAdapter = $cookieAdapter;
        $this->apyKeyAdapter = $apiKeyAdapter;
    }
    public function authenticate()
    {
         if ($this->ldapAdapter->authenticate()) {
             //return the Zend_Auth_Restult
         } elseif ($this->cookieAdapter->authenticate() {
            //return the result
         } elseif ($this->apiKeyAdapter->authenticate() {
           //return the result
         } else {
           //Create and return a Zend_Auth_Result which prevents logging in
          }
     }
}

I am not sure to understand your login rules, but the concept remains the same for the Storage class :

 <?php 
 class My_Auth_Storage implements Zend_Auth_Storage_Interface
  private $sessionStorage;
  private $cookieStorage;
  private $apiStorage;

  public function read()
  {
      if (!$this->sessionStorage->isEmpty())
      {
           return $this->sessionStorage->read();
      } elseif (!$this->cookieStorage->isEmpty())
      { 
           return $this->cookieStorage->read();
      } //And so one, do not forget to implement all the interface's methods

With this implementation, you can have multiple credential sources, and multiple session storage engines (cookie, session, db, or whatever you want to use).

For your acl concerns, you can fetch the LDAP group in you controller plugin and store it wherever you need, after authentication. You can then use a second plugin that checks ACLs on each request.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top