Zend_Auth

Introduction

Zend_Auth provides an API for authentication and includes concrete authentication adapters for common use case scenarios.

Zend_Auth is concerned only with authentication and not with authorization. Authentication is loosely defined as determining whether an entity actually is what it purports to be (i.e., identification), based on some set of credentials. Authorization, the process of deciding whether to allow an entity access to, or to perform operations upon, other entities is outside the scope of Zend_Auth. For more information about authorization and access control with Zend Framework, please see Zend_Acl.

Note: The Zend_Auth class implements the Singleton pattern - only one instance of the class is available - through its static getInstance() method. This means that using the new operator and the clone keyword will not work with the Zend_Auth class; use Zend_Auth::getInstance() instead.

Adapters

A Zend_Auth adapter is used to authenticate against a particular type of authentication service, such as LDAP, RDBMS, or file-based storage. Different adapters are likely to have vastly different options and behaviors, but some basic things are common among authentication adapters. For example, accepting authentication credentials (including a purported identity), performing queries against the authentication service, and returning results are common to Zend_Auth adapters.

Each Zend_Auth adapter class implements Zend_Auth_Adapter_Interface. This interface defines one method, authenticate(), that an adapter class must implement for performing an authentication query. Each adapter class must be prepared prior to calling authenticate(). Such adapter preparation includes setting up credentials (e.g., username and password) and defining values for adapter-specific configuration options, such as database connection settings for a database table adapter.

The following is an example authentication adapter that requires a username and password to be set for authentication. Other details, such as how the authentication service is queried, have been omitted for brevity:

  1. span style="color: #808080; font-style: italic;">/**
  2.      * Sets username and password for authentication
  3.      *
  4.      * @return void
  5.      */// ...
  6.     }
  7.  
  8.     /**
  9.      * Performs an authentication attempt
  10.      *
  11.      * @throws Zend_Auth_Adapter_Exception If authentication cannot
  12.      *                                     be performed
  13.      * @return Zend_Auth_Result
  14.      */// ...
  15.     }
  16. }

As indicated in its docblock, authenticate() must return an instance of Zend_Auth_Result (or of a class derived from Zend_Auth_Result). If for some reason performing an authentication query is impossible, authenticate() should throw an exception that derives from Zend_Auth_Adapter_Exception.

Results

Zend_Auth adapters return an instance of Zend_Auth_Result with authenticate() in order to represent the results of an authentication attempt. Adapters populate the Zend_Auth_Result object upon construction, so that the following four methods provide a basic set of user-facing operations that are common to the results of Zend_Auth adapters:

  • isValid() - returns TRUE if and only if the result represents a successful authentication attempt

  • getCode() - returns a Zend_Auth_Result constant identifier for determining the type of authentication failure or whether success has occurred. This may be used in situations where the developer wishes to distinguish among several authentication result types. This allows developers to maintain detailed authentication result statistics, for example. Another use of this feature is to provide specific, customized messages to users for usability reasons, though developers are encouraged to consider the risks of providing such detailed reasons to users, instead of a general authentication failure message. For more information, see the notes below.

  • getIdentity() - returns the identity of the authentication attempt

  • getMessages() - returns an array of messages regarding a failed authentication attempt

A developer may wish to branch based on the type of authentication result in order to perform more specific operations. Some operations developers might find useful are locking accounts after too many unsuccessful password attempts, flagging an IP address after too many nonexistent identities are attempted, and providing specific, customized authentication result messages to the user. The following result codes are available:

  1.  

The following example illustrates how a developer may branch on the result code:

  1. // inside of AuthController / loginAction
  2. /** do stuff for nonexistent identity **//** do stuff for invalid credential **//** do stuff for successful authentication **//** do stuff for other failure **/

Identity Persistence

Authenticating a request that includes authentication credentials is useful per se, but it is also important to support maintaining the authenticated identity without having to present the authentication credentials with each request.

HTTP is a stateless protocol, however, and techniques such as cookies and sessions have been developed in order to facilitate maintaining state across multiple requests in server-side web applications.

Default Persistence in the PHP Session

By default, Zend_Auth provides persistent storage of the identity from a successful authentication attempt using the PHP session. Upon a successful authentication attempt, Zend_Auth::authenticate() stores the identity from the authentication result into persistent storage. Unless configured otherwise, Zend_Auth uses a storage class named Zend_Auth_Storage_Session, which, in turn, uses Zend_Session. A custom class may instead be used by providing an object that implements Zend_Auth_Storage_Interface to Zend_Auth::setStorage().

Note: If automatic persistent storage of the identity is not appropriate for a particular use case, then developers may forgot using the Zend_Auth class altogether, instead using an adapter class directly.

Example #1 Modifying the Session Namespace

Zend_Auth_Storage_Session uses a session namespace of 'Zend_Auth'. This namespace may be overridden by passing a different value to the constructor of Zend_Auth_Storage_Session, and this value is internally passed along to the constructor of Zend_Session_Namespace. This should occur before authentication is attempted, since Zend_Auth::authenticate() performs the automatic storage of the identity.

  1. // Save a reference to the Singleton instance of Zend_Auth
  2. // Use 'someNamespace' instead of 'Zend_Auth'
  3. 'someNamespace'));
  4.  
  5. /**
  6. * @todo Set up the auth adapter, $authAdapter
  7. */
  8.  
  9. // Authenticate, saving the result, and persisting the identity on
  10. // success
  11. $result = $auth->authenticate($authAdapter);

Implementing Customized Storage

Sometimes developers may need to use a different identity storage mechanism than that provided by Zend_Auth_Storage_Session. For such cases developers may simply implement Zend_Auth_Storage_Interface and supply an instance of the class to Zend_Auth::setStorage().

Example #2 Using a Custom Storage Class

In order to use an identity persistence storage class other than Zend_Auth_Storage_Session, a developer implements Zend_Auth_Storage_Interface:

  1. span style="color: #808080; font-style: italic;">/**
  2.      * Returns true if and only if storage is empty
  3.      *
  4.      * @throws Zend_Auth_Storage_Exception If it is impossible to
  5.      *                                     determine whether storage
  6.      *                                     is empty
  7.      * @return boolean
  8.      *//**
  9.          * @todo implementation
  10.          */
  11.     }
  12.  
  13.     /**
  14.      * Returns the contents of storage
  15.      *
  16.      * Behavior is undefined when storage is empty.
  17.      *
  18.      * @throws Zend_Auth_Storage_Exception If reading contents from
  19.      *                                     storage is impossible
  20.      * @return mixed
  21.      *//**
  22.          * @todo implementation
  23.          */
  24.     }
  25.  
  26.     /**
  27.      * Writes $contents to storage
  28.      *
  29.      * @param  mixed $contents
  30.      * @throws Zend_Auth_Storage_Exception If writing $contents to
  31.      *                                     storage is impossible
  32.      * @return void
  33.      *//**
  34.          * @todo implementation
  35.          */
  36.     }
  37.  
  38.     /**
  39.      * Clears contents from storage
  40.      *
  41.      * @throws Zend_Auth_Storage_Exception If clearing contents from
  42.      *                                     storage is impossible
  43.      * @return void
  44.      *//**
  45.          * @todo implementation
  46.          */
  47.     }
  48. }

In order to use this custom storage class, Zend_Auth::setStorage() is invoked before an authentication query is attempted:

  1. // Instruct Zend_Auth to use the custom storage class
  2. /**
  3. * @todo Set up the auth adapter, $authAdapter
  4. */
  5.  
  6. // Authenticate, saving the result, and persisting the identity on
  7. // success

Usage

There are two provided ways to use Zend_Auth adapters:

  1. indirectly, through Zend_Auth::authenticate()

  2. directly, through the adapter's authenticate() method

The following example illustrates how to use a Zend_Auth adapter indirectly, through the use of the Zend_Auth class:

  1. // Get a reference to the singleton instance of Zend_Auth
  2. // Set up the authentication adapter
  3. // Attempt authentication, saving the result
  4. // Authentication failed; print the reasons why
  5. "$message\n"// Authentication succeeded; the identity ($username) is stored
  6.     // in the session
  7.     // $result->getIdentity() === $auth->getIdentity()
  8.     // $result->getIdentity() === $username
  9. }

Once authentication has been attempted in a request, as in the above example, it is a simple matter to check whether a successfully authenticated identity exists:

  1. span style="color: #808080; font-style: italic;">// Identity exists; get it
  2.     $identity = $auth->getIdentity();
  3. }

To remove an identity from persistent storage, simply use the clearIdentity() method. This typically would be used for implementing an application "logout" operation:

  1.  

When the automatic use of persistent storage is inappropriate for a particular use case, a developer may simply bypass the use of the Zend_Auth class, using an adapter class directly. Direct use of an adapter class involves configuring and preparing an adapter object and then calling its authenticate() method. Adapter-specific details are discussed in the documentation for each adapter. The following example directly utilizes MyAuthAdapter:

  1. // Set up the authentication adapter
  2. // Attempt authentication, saving the result
  3. // Authentication failed; print the reasons why
  4. "$message\n"// Authentication succeeded
  5.     // $result->getIdentity() === $username
  6. }

Zend_Auth