1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.auth.introduction">
4 <title>Introduction</title>
7 <classname>Zend_Auth</classname> provides an <acronym>API</acronym> for authentication and
8 includes concrete authentication adapters for common use case scenarios.
12 <classname>Zend_Auth</classname> is concerned only with <emphasis>authentication</emphasis>
13 and not with <emphasis>authorization</emphasis>. Authentication is loosely defined as
14 determining whether an entity actually is what it purports to be (i.e., identification),
15 based on some set of credentials. Authorization, the process of deciding whether to allow
16 an entity access to, or to perform operations upon, other entities is outside the scope of
17 <classname>Zend_Auth</classname>. For more information about authorization and access
18 control with Zend Framework, please see <link
19 linkend="zend.acl"><classname>Zend_Acl</classname></link>.
24 The <classname>Zend_Auth</classname> class implements the Singleton pattern - only one
25 instance of the class is available - through its static
26 <methodname>getInstance()</methodname> method. This means that using the
27 <emphasis>new</emphasis> operator and the <emphasis>clone</emphasis> keyword will not
28 work with the <classname>Zend_Auth</classname> class; use
29 <methodname>Zend_Auth::getInstance()</methodname> instead.
33 <sect2 id="zend.auth.introduction.adapters">
34 <title>Adapters</title>
37 A <classname>Zend_Auth</classname> adapter is used to authenticate against a particular
38 type of authentication service, such as <acronym>LDAP</acronym>,
39 <acronym>RDBMS</acronym>, or file-based storage. Different adapters are likely to have
40 vastly different options and behaviors, but some basic things are common among
41 authentication adapters. For example, accepting authentication credentials (including a
42 purported identity), performing queries against the authentication service, and
43 returning results are common to <classname>Zend_Auth</classname> adapters.
47 Each <classname>Zend_Auth</classname> adapter class implements
48 <classname>Zend_Auth_Adapter_Interface</classname>. This interface defines one method,
49 <methodname>authenticate()</methodname>, that an adapter class must implement for
50 performing an authentication query. Each adapter class must be prepared prior to
51 calling <methodname>authenticate()</methodname>. Such adapter preparation includes
52 setting up credentials (e.g., username and password) and defining values for
53 adapter-specific configuration options, such as database connection settings for a
54 database table adapter.
58 The following is an example authentication adapter that requires a username and
59 password to be set for authentication. Other details, such as how the authentication
60 service is queried, have been omitted for brevity:
63 <programlisting language="php"><![CDATA[
64 class MyAuthAdapter implements Zend_Auth_Adapter_Interface
67 * Sets username and password for authentication
71 public function __construct($username, $password)
77 * Performs an authentication attempt
79 * @throws Zend_Auth_Adapter_Exception If authentication cannot
81 * @return Zend_Auth_Result
83 public function authenticate()
91 As indicated in its docblock, <methodname>authenticate()</methodname> must return an
92 instance of <classname>Zend_Auth_Result</classname> (or of a class derived from
93 <classname>Zend_Auth_Result</classname>). If for some reason performing an
94 authentication query is impossible, <methodname>authenticate()</methodname> should
95 throw an exception that derives from
96 <classname>Zend_Auth_Adapter_Exception</classname>.
100 <sect2 id="zend.auth.introduction.results">
101 <title>Results</title>
104 <classname>Zend_Auth</classname> adapters return an instance of
105 <classname>Zend_Auth_Result</classname> with <methodname>authenticate()</methodname> in
106 order to represent the results of an authentication attempt. Adapters populate the
107 <classname>Zend_Auth_Result</classname> object upon construction, so that the following
108 four methods provide a basic set of user-facing operations that are common to the
109 results of <classname>Zend_Auth</classname> adapters:
115 <methodname>isValid()</methodname> - returns <constant>TRUE</constant> if and
116 only if the result represents a successful authentication attempt
122 <methodname>getCode()</methodname> - returns a
123 <classname>Zend_Auth_Result</classname> constant identifier for determining
124 the type of authentication failure or whether success has occurred. This
125 may be used in situations where the developer wishes to distinguish among
126 several authentication result types. This allows developers to maintain
127 detailed authentication result statistics, for example. Another use of this
128 feature is to provide specific, customized messages to users for usability
129 reasons, though developers are encouraged to consider the risks of
130 providing such detailed reasons to users, instead of a general
131 authentication failure message. For more information, see the notes below.
137 <methodname>getIdentity()</methodname> - returns the identity of the
138 authentication attempt
144 <methodname>getMessages()</methodname> - returns an array of messages
145 regarding a failed authentication attempt
151 A developer may wish to branch based on the type of authentication result in order to
152 perform more specific operations. Some operations developers might find useful are
153 locking accounts after too many unsuccessful password attempts, flagging an IP address
154 after too many nonexistent identities are attempted, and providing specific, customized
155 authentication result messages to the user. The following result codes are available:
158 <programlisting language="php"><![CDATA[
159 Zend_Auth_Result::SUCCESS
160 Zend_Auth_Result::FAILURE
161 Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND
162 Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS
163 Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID
164 Zend_Auth_Result::FAILURE_UNCATEGORIZED
168 The following example illustrates how a developer may branch on the result code:
171 <programlisting language="php"><![CDATA[
172 // inside of AuthController / loginAction
173 $result = $this->_auth->authenticate($adapter);
175 switch ($result->getCode()) {
177 case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
178 /** do stuff for nonexistent identity **/
181 case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
182 /** do stuff for invalid credential **/
185 case Zend_Auth_Result::SUCCESS:
186 /** do stuff for successful authentication **/
190 /** do stuff for other failure **/
196 <sect2 id="zend.auth.introduction.persistence">
197 <title>Identity Persistence</title>
200 Authenticating a request that includes authentication credentials is useful per se, but
201 it is also important to support maintaining the authenticated identity without having
202 to present the authentication credentials with each request.
206 <acronym>HTTP</acronym> is a stateless protocol, however, and techniques such as
207 cookies and sessions have been developed in order to facilitate maintaining state
208 across multiple requests in server-side web applications.
211 <sect3 id="zend.auth.introduction.persistence.default">
212 <title>Default Persistence in the PHP Session</title>
215 By default, <classname>Zend_Auth</classname> provides persistent storage of the
216 identity from a successful authentication attempt using the <acronym>PHP</acronym>
217 session. Upon a successful authentication attempt,
218 <methodname>Zend_Auth::authenticate()</methodname> stores the identity from the
219 authentication result into persistent storage. Unless configured otherwise,
220 <classname>Zend_Auth</classname> uses a storage class named
221 <classname>Zend_Auth_Storage_Session</classname>, which, in turn, uses
222 <link linkend="zend.session"><classname>Zend_Session</classname></link>. A custom
223 class may instead be used by providing an object that implements
224 <classname>Zend_Auth_Storage_Interface</classname> to
225 <methodname>Zend_Auth::setStorage()</methodname>.
230 If automatic persistent storage of the identity is not appropriate for a
231 particular use case, then developers may forgot using the
232 <classname>Zend_Auth</classname> class altogether, instead using an adapter
237 <example id="zend.auth.introduction.persistence.default.example">
238 <title>Modifying the Session Namespace</title>
241 <classname>Zend_Auth_Storage_Session</classname> uses a session namespace of
242 '<classname>Zend_Auth</classname>'. This namespace may be overridden by passing
243 a different value to the constructor of
244 <classname>Zend_Auth_Storage_Session</classname>, and this value is internally
245 passed along to the constructor of
246 <classname>Zend_Session_Namespace</classname>. This should occur before
247 authentication is attempted, since
248 <methodname>Zend_Auth::authenticate()</methodname> performs the automatic
249 storage of the identity.
252 <programlisting language="php"><![CDATA[
253 // Save a reference to the Singleton instance of Zend_Auth
254 $auth = Zend_Auth::getInstance();
256 // Use 'someNamespace' instead of 'Zend_Auth'
257 $auth->setStorage(new Zend_Auth_Storage_Session('someNamespace'));
260 * @todo Set up the auth adapter, $authAdapter
263 // Authenticate, saving the result, and persisting the identity on
265 $result = $auth->authenticate($authAdapter);
270 <sect3 id="zend.auth.introduction.persistence.custom">
271 <title>Implementing Customized Storage</title>
274 Sometimes developers may need to use a different identity storage mechanism than
275 that provided by <classname>Zend_Auth_Storage_Session</classname>. For such cases
276 developers may simply implement <classname>Zend_Auth_Storage_Interface</classname>
277 and supply an instance of the class to
278 <methodname>Zend_Auth::setStorage()</methodname>.
281 <example id="zend.auth.introduction.persistence.custom.example">
282 <title>Using a Custom Storage Class</title>
285 In order to use an identity persistence storage class other than
286 <classname>Zend_Auth_Storage_Session</classname>, a developer implements
287 <classname>Zend_Auth_Storage_Interface</classname>:
290 <programlisting language="php"><![CDATA[
291 class MyStorage implements Zend_Auth_Storage_Interface
294 * Returns true if and only if storage is empty
296 * @throws Zend_Auth_Storage_Exception If it is impossible to
297 * determine whether storage
301 public function isEmpty()
304 * @todo implementation
309 * Returns the contents of storage
311 * Behavior is undefined when storage is empty.
313 * @throws Zend_Auth_Storage_Exception If reading contents from
314 * storage is impossible
317 public function read()
320 * @todo implementation
325 * Writes $contents to storage
327 * @param mixed $contents
328 * @throws Zend_Auth_Storage_Exception If writing $contents to
329 * storage is impossible
332 public function write($contents)
335 * @todo implementation
340 * Clears contents from storage
342 * @throws Zend_Auth_Storage_Exception If clearing contents from
343 * storage is impossible
346 public function clear()
349 * @todo implementation
356 In order to use this custom storage class,
357 <methodname>Zend_Auth::setStorage()</methodname> is invoked before an
358 authentication query is attempted:
361 <programlisting language="php"><![CDATA[
362 // Instruct Zend_Auth to use the custom storage class
363 Zend_Auth::getInstance()->setStorage(new MyStorage());
366 * @todo Set up the auth adapter, $authAdapter
369 // Authenticate, saving the result, and persisting the identity on
371 $result = Zend_Auth::getInstance()->authenticate($authAdapter);
377 <sect2 id="zend.auth.introduction.using">
381 There are two provided ways to use <classname>Zend_Auth</classname> adapters:
387 indirectly, through <methodname>Zend_Auth::authenticate()</methodname>
393 directly, through the adapter's <methodname>authenticate()</methodname> method
399 The following example illustrates how to use a <classname>Zend_Auth</classname> adapter
400 indirectly, through the use of the <classname>Zend_Auth</classname> class:
403 <programlisting language="php"><![CDATA[
404 // Get a reference to the singleton instance of Zend_Auth
405 $auth = Zend_Auth::getInstance();
407 // Set up the authentication adapter
408 $authAdapter = new MyAuthAdapter($username, $password);
410 // Attempt authentication, saving the result
411 $result = $auth->authenticate($authAdapter);
413 if (!$result->isValid()) {
414 // Authentication failed; print the reasons why
415 foreach ($result->getMessages() as $message) {
419 // Authentication succeeded; the identity ($username) is stored
421 // $result->getIdentity() === $auth->getIdentity()
422 // $result->getIdentity() === $username
427 Once authentication has been attempted in a request, as in the above example, it is a
428 simple matter to check whether a successfully authenticated identity exists:
431 <programlisting language="php"><![CDATA[
432 $auth = Zend_Auth::getInstance();
433 if ($auth->hasIdentity()) {
434 // Identity exists; get it
435 $identity = $auth->getIdentity();
440 To remove an identity from persistent storage, simply use the
441 <methodname>clearIdentity()</methodname> method. This typically would be used for
442 implementing an application "logout" operation:
445 <programlisting language="php"><![CDATA[
446 Zend_Auth::getInstance()->clearIdentity();
450 When the automatic use of persistent storage is inappropriate for a particular use
451 case, a developer may simply bypass the use of the <classname>Zend_Auth</classname>
452 class, using an adapter class directly. Direct use of an adapter class involves
453 configuring and preparing an adapter object and then calling its
454 <methodname>authenticate()</methodname> method. Adapter-specific details are discussed
455 in the documentation for each adapter. The following example directly utilizes
456 <classname>MyAuthAdapter</classname>:
459 <programlisting language="php"><![CDATA[
460 // Set up the authentication adapter
461 $authAdapter = new MyAuthAdapter($username, $password);
463 // Attempt authentication, saving the result
464 $result = $authAdapter->authenticate();
466 if (!$result->isValid()) {
467 // Authentication failed; print the reasons why
468 foreach ($result->getMessages() as $message) {
472 // Authentication succeeded
473 // $result->getIdentity() === $username