Zend_Auth_Adapter_Ldap.xml 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.auth.adapter.ldap">
  4. <title>LDAP Authentication</title>
  5. <sect2 id="zend.auth.adapter.ldap.introduction">
  6. <title>Introduction</title>
  7. <para>
  8. <classname>Zend_Auth_Adapter_Ldap</classname> supports web application authentication
  9. with <acronym>LDAP</acronym> services. Its features include username and domain name
  10. canonicalization, multi-domain authentication, and failover capabilities. It has been
  11. tested to work with
  12. <ulink
  13. url="http://www.microsoft.com/windowsserver2003/technologies/directory/activedirectory/">Microsoft
  14. Active Directory</ulink> and <ulink url="http://www.openldap.org/">OpenLDAP</ulink>,
  15. but it should also work with other <acronym>LDAP</acronym> service providers.
  16. </para>
  17. <para>
  18. This documentation includes a guide on using
  19. <classname>Zend_Auth_Adapter_Ldap</classname>, an exploration of its
  20. <acronym>API</acronym>, an outline of the various available options, diagnostic
  21. information for troubleshooting authentication problems, and example options for both
  22. Active Directory and OpenLDAP servers.
  23. </para>
  24. </sect2>
  25. <sect2 id="zend.auth.adapter.ldap.usage">
  26. <title>Usage</title>
  27. <para>
  28. To incorporate <classname>Zend_Auth_Adapter_Ldap</classname> authentication into your
  29. application quickly, even if you're not using <classname>Zend_Controller</classname>,
  30. the meat of your code should look something like the following:
  31. </para>
  32. <programlisting language="php"><![CDATA[
  33. $username = $this->_request->getParam('username');
  34. $password = $this->_request->getParam('password');
  35. $auth = Zend_Auth::getInstance();
  36. $config = new Zend_Config_Ini('../application/config/config.ini',
  37. 'production');
  38. $log_path = $config->ldap->log_path;
  39. $options = $config->ldap->toArray();
  40. unset($options['log_path']);
  41. $adapter = new Zend_Auth_Adapter_Ldap($options, $username,
  42. $password);
  43. $result = $auth->authenticate($adapter);
  44. if ($log_path) {
  45. $messages = $result->getMessages();
  46. $logger = new Zend_Log();
  47. $logger->addWriter(new Zend_Log_Writer_Stream($log_path));
  48. $filter = new Zend_Log_Filter_Priority(Zend_Log::DEBUG);
  49. $logger->addFilter($filter);
  50. foreach ($messages as $i => $message) {
  51. if ($i-- > 1) { // $messages[2] and up are log messages
  52. $message = str_replace("\n", "\n ", $message);
  53. $logger->log("Ldap: $i: $message", Zend_Log::DEBUG);
  54. }
  55. }
  56. }
  57. ]]></programlisting>
  58. <para>
  59. Of course, the logging code is optional, but it is highly recommended that you use a
  60. logger. <classname>Zend_Auth_Adapter_Ldap</classname> will record just about every bit
  61. of information anyone could want in <varname>$messages</varname> (more below), which is
  62. a nice feature in itself for something that has a history of being notoriously difficult
  63. to debug.
  64. </para>
  65. <para>
  66. The <classname>Zend_Config_Ini</classname> code is used above to load the adapter
  67. options. It is also optional. A regular array would work equally well. The following is
  68. an example <filename>application/config/config.ini</filename> file that has options for
  69. two separate servers. With multiple sets of server options the adapter will try each, in
  70. order, until the credentials are successfully authenticated. The names of the servers
  71. (e.g., 'server1' and 'server2') are largely arbitrary. For details regarding the options
  72. array, see the <emphasis>Server Options</emphasis> section below. Note that
  73. <classname>Zend_Config_Ini</classname> requires that any values with "equals" characters
  74. (<emphasis>=</emphasis>) will need to be quoted (like the DNs shown below).
  75. </para>
  76. <programlisting language="ini"><![CDATA[
  77. [production]
  78. ldap.log_path = /tmp/ldap.log
  79. ; Typical options for OpenLDAP
  80. ldap.server1.host = s0.foo.net
  81. ldap.server1.accountDomainName = foo.net
  82. ldap.server1.accountDomainNameShort = FOO
  83. ldap.server1.accountCanonicalForm = 3
  84. ldap.server1.username = "CN=user1,DC=foo,DC=net"
  85. ldap.server1.password = pass1
  86. ldap.server1.baseDn = "OU=Sales,DC=foo,DC=net"
  87. ldap.server1.bindRequiresDn = true
  88. ; Typical options for Active Directory
  89. ldap.server2.host = dc1.w.net
  90. ldap.server2.useStartTls = true
  91. ldap.server2.accountDomainName = w.net
  92. ldap.server2.accountDomainNameShort = W
  93. ldap.server2.accountCanonicalForm = 3
  94. ldap.server2.baseDn = "CN=Users,DC=w,DC=net"
  95. ]]></programlisting>
  96. <para>
  97. The above configuration will instruct <classname>Zend_Auth_Adapter_Ldap</classname> to
  98. attempt to authenticate users with the OpenLDAP server <filename>s0.foo.net</filename>
  99. first. If the authentication fails for any reason, the AD server
  100. <filename>dc1.w.net</filename> will be tried.
  101. </para>
  102. <para>
  103. With servers in different domains, this configuration illustrates multi-domain
  104. authentication. You can also have multiple servers in the same domain to provide
  105. redundancy.
  106. </para>
  107. <para>
  108. Note that in this case, even though OpenLDAP has no need for the short NetBIOS style
  109. domain name used by Windows, we provide it here for name canonicalization purposes
  110. (described in the <emphasis>Username Canonicalization</emphasis> section below).
  111. </para>
  112. </sect2>
  113. <sect2 id="zend.auth.adapter.ldap.api">
  114. <title>The API</title>
  115. <para>
  116. The <classname>Zend_Auth_Adapter_Ldap</classname> constructor accepts three parameters.
  117. </para>
  118. <para>
  119. The <varname>$options</varname> parameter is required and must be an array containing
  120. one or more sets of options. Note that it is <emphasis>an array of arrays</emphasis> of
  121. <link linkend="zend.ldap"><classname>Zend_Ldap</classname></link> options. Even if you
  122. will be using only one <acronym>LDAP</acronym> server, the options must still be within
  123. another array.
  124. </para>
  125. <para>
  126. Below is <ulink url="http://php.net/print_r"><methodname>print_r()</methodname></ulink>
  127. output of an example options parameter containing two sets of server options for
  128. <acronym>LDAP</acronym> servers <filename>s0.foo.net</filename> and
  129. <filename>dc1.w.net</filename> (the same options as the above <acronym>INI</acronym>
  130. representation):
  131. </para>
  132. <programlisting language="output"><![CDATA[
  133. Array
  134. (
  135. [server2] => Array
  136. (
  137. [host] => dc1.w.net
  138. [useStartTls] => 1
  139. [accountDomainName] => w.net
  140. [accountDomainNameShort] => W
  141. [accountCanonicalForm] => 3
  142. [baseDn] => CN=Users,DC=w,DC=net
  143. )
  144. [server1] => Array
  145. (
  146. [host] => s0.foo.net
  147. [accountDomainName] => foo.net
  148. [accountDomainNameShort] => FOO
  149. [accountCanonicalForm] => 3
  150. [username] => CN=user1,DC=foo,DC=net
  151. [password] => pass1
  152. [baseDn] => OU=Sales,DC=foo,DC=net
  153. [bindRequiresDn] => 1
  154. )
  155. )
  156. ]]></programlisting>
  157. <para>
  158. The information provided in each set of options above is different mainly because AD
  159. does not require a username be in DN form when binding (see the
  160. <emphasis>bindRequiresDn</emphasis> option in the <emphasis>Server Options</emphasis>
  161. section below), which means we can omit a number of options associated with retrieving
  162. the DN for a username being authenticated.
  163. </para>
  164. <note>
  165. <title>What is a Distinguished Name?</title>
  166. <para>
  167. A DN or "distinguished name" is a string that represents the path to an object
  168. within the <acronym>LDAP</acronym> directory. Each comma-separated component is an
  169. attribute and value representing a node. The components are evaluated in reverse.
  170. For example, the user account
  171. <emphasis>CN=Bob Carter,CN=Users,DC=w,DC=net</emphasis> is located directly
  172. within the <emphasis>CN=Users,DC=w,DC=net container</emphasis>. This structure is
  173. best explored with an <acronym>LDAP</acronym> browser like the
  174. <acronym>ADSI</acronym> Edit <acronym>MMC</acronym> snap-in for Active Directory or
  175. phpLDAPadmin.
  176. </para>
  177. </note>
  178. <para>
  179. The names of servers (e.g. 'server1' and 'server2' shown above) are largely arbitrary,
  180. but for the sake of using <classname>Zend_Config</classname>, the identifiers should be
  181. present (as opposed to being numeric indexes) and should not contain any special
  182. characters used by the associated file formats (e.g. the '<emphasis>.</emphasis>'
  183. <acronym>INI</acronym> property separator, '<emphasis>&amp;</emphasis>' for
  184. <acronym>XML</acronym> entity references, etc).
  185. </para>
  186. <para>
  187. With multiple sets of server options, the adapter can authenticate users in multiple
  188. domains and provide failover so that if one server is not available, another will be
  189. queried.
  190. </para>
  191. <note>
  192. <title>The Gory Details: What Happens in the Authenticate Method?</title>
  193. <para>
  194. When the <methodname>authenticate()</methodname> method is called, the adapter
  195. iterates over each set of server options, sets them on the internal
  196. <classname>Zend_Ldap</classname> instance, and calls the
  197. <methodname>Zend_Ldap::bind()</methodname> method with the username and password
  198. being authenticated. The <classname>Zend_Ldap</classname> class checks to see if
  199. the username is qualified with a domain (e.g., has a domain component like
  200. <filename>alice@foo.net</filename> or <filename>FOO\alice</filename>). If a domain
  201. is present, but does not match either of the server's domain names
  202. (<filename>foo.net</filename> or <acronym>FOO</acronym>), a special exception is
  203. thrown and caught by <classname>Zend_Auth_Adapter_Ldap</classname> that causes that
  204. server to be ignored and the next set of server options is selected. If a domain
  205. <emphasis>does</emphasis> match, or if the user did not supply a qualified username,
  206. <classname>Zend_Ldap</classname> proceeds to try to bind with the supplied
  207. credentials. if the bind is not successful, <classname>Zend_Ldap</classname> throws
  208. a <classname>Zend_Ldap_Exception</classname> which is caught by
  209. <classname>Zend_Auth_Adapter_Ldap</classname> and the next set of server options is
  210. tried. If the bind is successful, the iteration stops, and the adapter's
  211. <methodname>authenticate()</methodname> method returns a successful result. If all
  212. server options have been tried without success, the authentication fails, and
  213. <methodname>authenticate()</methodname> returns a failure result with error messages
  214. from the last iteration.
  215. </para>
  216. </note>
  217. <para>
  218. The username and password parameters of the
  219. <classname>Zend_Auth_Adapter_Ldap</classname> constructor represent the credentials
  220. being authenticated (i.e., the credentials supplied by the user through your
  221. <acronym>HTML</acronym> login form). Alternatively, they may also be set with the
  222. <methodname>setUsername()</methodname> and <methodname>setPassword()</methodname>
  223. methods.
  224. </para>
  225. </sect2>
  226. <sect2 id="zend.auth.adapter.ldap.server-options">
  227. <title>Server Options</title>
  228. <para>
  229. Each set of server options <emphasis>in the context of
  230. <classname>Zend_Auth_Adapter_Ldap</classname></emphasis> consists of the following
  231. options, which are passed, largely unmodified, to
  232. <methodname>Zend_Ldap::setOptions()</methodname>:
  233. </para>
  234. <table id="zend.auth.adapter.ldap.server-options.table">
  235. <title>Server Options</title>
  236. <tgroup cols="2">
  237. <thead>
  238. <row>
  239. <entry>Name</entry>
  240. <entry>Description</entry>
  241. </row>
  242. </thead>
  243. <tbody>
  244. <row>
  245. <entry><emphasis>host</emphasis></entry>
  246. <entry>
  247. The hostname of <acronym>LDAP</acronym> server that these options
  248. represent. This option is required.
  249. </entry>
  250. </row>
  251. <row>
  252. <entry><emphasis>port</emphasis></entry>
  253. <entry>
  254. The port on which the <acronym>LDAP</acronym> server is listening. If
  255. <emphasis>useSsl</emphasis> is <constant>TRUE</constant>, the default
  256. <emphasis>port</emphasis> value is 636. if <emphasis>useSsl</emphasis>
  257. is <constant>FALSE</constant>, the default <emphasis>port</emphasis>
  258. value is 389.
  259. </entry>
  260. </row>
  261. <row>
  262. <entry>useStartTls</entry>
  263. <entry>
  264. Whether or not the <acronym>LDAP</acronym> client should use
  265. <acronym>TLS</acronym> (aka SSLv2) encrypted transport. A value of
  266. <constant>TRUE</constant> is strongly favored in production
  267. environments to prevent passwords from be transmitted in clear text.
  268. The default value is <constant>FALSE</constant>, as servers frequently
  269. require that a certificate be installed separately after installation.
  270. The <emphasis>useSsl</emphasis> and <emphasis>useStartTls</emphasis>
  271. options are mutually exclusive. The <emphasis>useStartTls</emphasis>
  272. option should be favored over <emphasis>useSsl</emphasis> but not all
  273. servers support this newer mechanism.
  274. </entry>
  275. </row>
  276. <row>
  277. <entry>useSsl</entry>
  278. <entry>
  279. Whether or not the <acronym>LDAP</acronym> client should use
  280. <acronym>SSL</acronym> encrypted transport. The
  281. <emphasis>useSsl</emphasis> and <emphasis>useStartTls</emphasis>
  282. options are mutually exclusive, but <emphasis>useStartTls</emphasis>
  283. should be favored if the server and <acronym>LDAP</acronym> client
  284. library support it. This value also changes the default
  285. <emphasis>port</emphasis> value (see <emphasis>port</emphasis>
  286. description above).
  287. </entry>
  288. </row>
  289. <row>
  290. <entry><emphasis>username</emphasis></entry>
  291. <entry>
  292. The DN of the account used to perform account DN lookups.
  293. <acronym>LDAP</acronym> servers that require the username to be in DN
  294. form when performing the "bind" require this option. Meaning, if
  295. <emphasis>bindRequiresDn</emphasis> is <constant>TRUE</constant>, this
  296. option is required. This account does not need to be a privileged
  297. account; an account with read-only access to objects under the
  298. <emphasis>baseDn</emphasis> is all that is necessary (and preferred
  299. based on the <emphasis>Principle of Least Privilege</emphasis>).
  300. </entry>
  301. </row>
  302. <row>
  303. <entry><emphasis>password</emphasis></entry>
  304. <entry>
  305. The password of the account used to perform account DN lookups. If this
  306. option is not supplied, the <acronym>LDAP</acronym> client will attempt
  307. an "anonymous bind" when performing account DN lookups.
  308. </entry>
  309. </row>
  310. <row>
  311. <entry><emphasis>bindRequiresDn</emphasis></entry>
  312. <entry>
  313. Some <acronym>LDAP</acronym> servers require that the username used to
  314. bind be in DN form like
  315. <emphasis>CN=Alice Baker,OU=Sales,DC=foo,DC=net</emphasis> (basically
  316. all servers <emphasis>except</emphasis> AD). If this option is
  317. <constant>TRUE</constant>, this instructs
  318. <classname>Zend_Ldap</classname> to automatically retrieve the DN
  319. corresponding to the username being authenticated, if it is not already
  320. in DN form, and then re-bind with the proper DN. The default value is
  321. <constant>FALSE</constant>. Currently only Microsoft Active Directory
  322. Server (<acronym>ADS</acronym>) is known <emphasis>not</emphasis> to
  323. require usernames to be in DN form when binding, and therefore this
  324. option may be <constant>FALSE</constant> with AD (and it should be, as
  325. retrieving the DN requires an extra round trip to the server).
  326. Otherwise, this option must be set to <constant>TRUE</constant> (e.g.
  327. for OpenLDAP). This option also controls the default
  328. <emphasis>acountFilterFormat</emphasis> used when searching for
  329. accounts. See the <emphasis>accountFilterFormat</emphasis> option.
  330. </entry>
  331. </row>
  332. <row>
  333. <entry><emphasis>baseDn</emphasis></entry>
  334. <entry>
  335. The DN under which all accounts being authenticated are located. This
  336. option is required. if you are uncertain about the correct
  337. <emphasis>baseDn</emphasis> value, it should be sufficient to derive it
  338. from the user's <acronym>DNS</acronym> domain using
  339. <emphasis>DC=</emphasis> components. For example, if the user's
  340. principal name is <filename>alice@foo.net</filename>, a
  341. <emphasis>baseDn</emphasis> of <emphasis>DC=foo,DC=net</emphasis>
  342. should work. A more precise location (e.g.,
  343. <emphasis>OU=Sales,DC=foo,DC=net</emphasis>) will be more efficient,
  344. however.
  345. </entry>
  346. </row>
  347. <row>
  348. <entry><emphasis>accountCanonicalForm</emphasis></entry>
  349. <entry>
  350. A value of 2, 3 or 4 indicating the form to which account names should
  351. be canonicalized after successful authentication. Values are as
  352. follows: 2 for traditional username style names (e.g.,
  353. <emphasis>alice</emphasis>), 3 for backslash-style names (e.g.,
  354. <filename>FOO\alice</filename>) or 4 for principal style usernames
  355. (e.g., <filename>alice@foo.net</filename>). The default value is 4
  356. (e.g., <filename>alice@foo.net</filename>). For example, with a value
  357. of 3, the identity returned by
  358. <methodname>Zend_Auth_Result::getIdentity()</methodname> (and
  359. <methodname>Zend_Auth::getIdentity()</methodname>, if
  360. <classname>Zend_Auth</classname> was used) will always be
  361. <filename>FOO\alice</filename>, regardless of what form Alice supplied,
  362. whether it be <emphasis>alice</emphasis>,
  363. <filename>alice@foo.net</filename>, <filename>FOO\alice</filename>,
  364. <filename>FoO\aLicE</filename>, <filename>foo.net\alice</filename>,
  365. etc. See the <emphasis>Account Name Canonicalization</emphasis> section
  366. in the <classname>Zend_Ldap</classname> documentation for details. Note
  367. that when using multiple sets of server options it is recommended, but
  368. not required, that the same <emphasis>accountCanonicalForm</emphasis>
  369. be used with all server options so that the resulting usernames are
  370. always canonicalized to the same form (e.g., if you canonicalize to
  371. <filename>EXAMPLE\username</filename> with an AD server but to
  372. <filename>username@example.com</filename> with an OpenLDAP server, that
  373. may be awkward for the application's high-level logic).
  374. </entry>
  375. </row>
  376. <row>
  377. <entry><emphasis>accountDomainName</emphasis></entry>
  378. <entry>
  379. The <acronym>FQDN</acronym> domain name for which the target
  380. <acronym>LDAP</acronym> server is an authority (e.g.,
  381. <filename>example.com</filename>). This option is used to canonicalize
  382. names so that the username supplied by the user can be converted as
  383. necessary for binding. It is also used to determine if the server is an
  384. authority for the supplied username (e.g., if
  385. <emphasis>accountDomainName</emphasis> is <filename>foo.net</filename>
  386. and the user supplies <filename>bob@bar.net</filename>, the server will
  387. not be queried, and a failure will result). This option is not
  388. required, but if it is not supplied, usernames in principal name form
  389. (e.g., <filename>alice@foo.net</filename>) are not supported. It is
  390. strongly recommended that you supply this option, as there are many
  391. use-cases that require generating the principal name form.
  392. </entry>
  393. </row>
  394. <row>
  395. <entry><emphasis>accountDomainNameShort</emphasis></entry>
  396. <entry>
  397. The 'short' domain for which the target <acronym>LDAP</acronym> server
  398. is an authority (e.g., <acronym>FOO</acronym>). Note that there is a
  399. 1:1 mapping between the <emphasis>accountDomainName</emphasis> and
  400. <emphasis>accountDomainNameShort</emphasis>. This option should be used
  401. to specify the NetBIOS domain name for Windows networks, but may also
  402. be used by non-AD servers (e.g., for consistency when multiple sets of
  403. server options with the backslash style
  404. <emphasis>accountCanonicalForm</emphasis>). This option is not required
  405. but if it is not supplied, usernames in backslash form (e.g.,
  406. <filename>FOO\alice</filename>) are not supported.
  407. </entry>
  408. </row>
  409. <row>
  410. <entry><emphasis>accountFilterFormat</emphasis></entry>
  411. <entry>
  412. The <acronym>LDAP</acronym> search filter used to search for accounts.
  413. This string is a <ulink
  414. url="http://php.net/printf"><methodname>printf()</methodname></ulink>-style
  415. expression that must contain one '<emphasis>%s</emphasis>' to
  416. accomodate the username. The default value is
  417. '<emphasis>(&amp;(objectClass=user)(sAMAccountName=%s))</emphasis>',
  418. unless <emphasis>bindRequiresDn</emphasis> is set to
  419. <constant>TRUE</constant>, in which case the default is
  420. '<emphasis>(&amp;(objectClass=posixAccount)(uid=%s))</emphasis>'. For
  421. example, if for some reason you wanted to use
  422. <emphasis>bindRequiresDn = true</emphasis> with AD you would need to
  423. set <emphasis>accountFilterFormat =
  424. '(&amp;(objectClass=user)(sAMAccountName=%s))</emphasis>'.
  425. </entry>
  426. </row>
  427. <row>
  428. <entry><emphasis>optReferrals</emphasis></entry>
  429. <entry>
  430. If set to <constant>TRUE</constant>, this option indicates to the
  431. <acronym>LDAP</acronym> client that referrals should be followed. The
  432. default value is <constant>FALSE</constant>.
  433. </entry>
  434. </row>
  435. </tbody>
  436. </tgroup>
  437. </table>
  438. <note>
  439. <para>
  440. If you enable <emphasis>useStartTls = true</emphasis> or
  441. <emphasis>useSsl = true</emphasis> you may find that the <acronym>LDAP</acronym>
  442. client generates an error claiming that it cannot validate the server's
  443. certificate. Assuming the <acronym>PHP</acronym> <acronym>LDAP</acronym> extension
  444. is ultimately linked to the OpenLDAP client libraries, to resolve this issue you
  445. can set "<command>TLS_REQCERT never</command>" in the OpenLDAP client
  446. <filename>ldap.conf</filename> (and restart the web server) to indicate to the
  447. OpenLDAP client library that you trust the server. Alternatively, if you are
  448. concerned that the server could be spoofed, you can export the
  449. <acronym>LDAP</acronym> server's root certificate and put it on the web server so
  450. that the OpenLDAP client can validate the server's identity.
  451. </para>
  452. </note>
  453. </sect2>
  454. <sect2 id="zend.auth.adapter.ldap.debugging">
  455. <title>Collecting Debugging Messages</title>
  456. <para>
  457. <classname>Zend_Auth_Adapter_Ldap</classname> collects debugging information within its
  458. <methodname>authenticate()</methodname> method. This information is stored in the
  459. <classname>Zend_Auth_Result</classname> object as messages. The array returned by
  460. <methodname>Zend_Auth_Result::getMessages()</methodname> is described as follows
  461. </para>
  462. <table id="zend.auth.adapter.ldap.debugging.table">
  463. <title>Debugging Messages</title>
  464. <tgroup cols="2">
  465. <thead>
  466. <row>
  467. <entry>Messages Array Index</entry>
  468. <entry>Description</entry>
  469. </row>
  470. </thead>
  471. <tbody>
  472. <row>
  473. <entry>Index 0</entry>
  474. <entry>
  475. A generic, user-friendly message that is suitable for displaying to
  476. users (e.g., "Invalid credentials"). If the authentication is
  477. successful, this string is empty.
  478. </entry>
  479. </row>
  480. <row>
  481. <entry>Index 1</entry>
  482. <entry>
  483. A more detailed error message that is not suitable to be displayed to
  484. users but should be logged for the benefit of server operators. If the
  485. authentication is successful, this string is empty.
  486. </entry>
  487. </row>
  488. <row>
  489. <entry>Indexes 2 and higher</entry>
  490. <entry>
  491. All log messages in order starting at index 2.
  492. </entry>
  493. </row>
  494. </tbody>
  495. </tgroup>
  496. </table>
  497. <para>
  498. In practice, index 0 should be displayed to the user (e.g., using the FlashMessenger
  499. helper), index 1 should be logged and, if debugging information is being collected,
  500. indexes 2 and higher could be logged as well (although the final message always includes
  501. the string from index 1).
  502. </para>
  503. </sect2>
  504. <sect2 id="zend.auth.adapter.ldap.options-common-server-specific">
  505. <title>Common Options for Specific Servers</title>
  506. <sect3 id="zend.auth.adapter.ldap.options-common-server-specific.active-directory">
  507. <title>Options for Active Directory</title>
  508. <para>
  509. For <acronym>ADS</acronym>, the following options are noteworthy:
  510. </para>
  511. <table
  512. id="zend.auth.adapter.ldap.options-common-server-specific.active-directory.table">
  513. <title>Options for Active Directory</title>
  514. <tgroup cols="2">
  515. <thead>
  516. <row>
  517. <entry>Name</entry>
  518. <entry>Additional Notes</entry>
  519. </row>
  520. </thead>
  521. <tbody>
  522. <row>
  523. <entry><emphasis>host</emphasis></entry>
  524. <entry>
  525. As with all servers, this option is required.
  526. </entry>
  527. </row>
  528. <row>
  529. <entry><emphasis>useStartTls</emphasis></entry>
  530. <entry>
  531. For the sake of security, this should be <constant>TRUE</constant>
  532. if the server has the necessary certificate installed.
  533. </entry>
  534. </row>
  535. <row>
  536. <entry><emphasis>useSsl</emphasis></entry>
  537. <entry>
  538. Possibly used as an alternative to <emphasis>useStartTls</emphasis>
  539. (see above).
  540. </entry>
  541. </row>
  542. <row>
  543. <entry><emphasis>baseDn</emphasis></entry>
  544. <entry>
  545. As with all servers, this option is required. By default AD places
  546. all user accounts under the <emphasis>Users</emphasis> container
  547. (e.g., <emphasis>CN=Users,DC=foo,DC=net</emphasis>), but the
  548. default is not common in larger organizations. Ask your AD
  549. administrator what the best DN for accounts for your application
  550. would be.
  551. </entry>
  552. </row>
  553. <row>
  554. <entry><emphasis>accountCanonicalForm</emphasis></entry>
  555. <entry>
  556. You almost certainly want this to be 3 for backslash style names
  557. (e.g., <filename>FOO\alice</filename>), which are most familiar to
  558. Windows users. You should <emphasis>not</emphasis> use the
  559. unqualified form 2 (e.g., <emphasis>alice</emphasis>), as this may
  560. grant access to your application to users with the same username in
  561. other trusted domains (e.g., <filename>BAR\alice</filename> and
  562. <filename>FOO\alice</filename> will be treated as the same user).
  563. (See also note below.)
  564. </entry>
  565. </row>
  566. <row>
  567. <entry><emphasis>accountDomainName</emphasis></entry>
  568. <entry>
  569. This is required with AD unless
  570. <emphasis>accountCanonicalForm</emphasis> 2 is used, which, again,
  571. is discouraged.
  572. </entry>
  573. </row>
  574. <row>
  575. <entry><emphasis>accountDomainNameShort</emphasis></entry>
  576. <entry>
  577. The NetBIOS name of the domain that users are in and for which the
  578. AD server is an authority. This is required if the backslash style
  579. <emphasis>accountCanonicalForm</emphasis> is used.
  580. </entry>
  581. </row>
  582. </tbody>
  583. </tgroup>
  584. </table>
  585. <note>
  586. <para>
  587. Technically there should be no danger of accidental cross-domain authentication
  588. with the current <classname>Zend_Auth_Adapter_Ldap</classname> implementation,
  589. since server domains are explicitly checked, but this may not be true of a
  590. future implementation that discovers the domain at runtime, or if an alternative
  591. adapter is used (e.g., Kerberos). In general, account name ambiguity is known to
  592. be the source of security issues, so always try to use qualified account names.
  593. </para>
  594. </note>
  595. </sect3>
  596. <sect3 id="zend.auth.adapter.ldap.options-common-server-specific.openldap">
  597. <title>Options for OpenLDAP</title>
  598. <para>
  599. For OpenLDAP or a generic <acronym>LDAP</acronym> server using a typical
  600. posixAccount style schema, the following options are noteworthy:
  601. </para>
  602. <table id="zend.auth.adapter.ldap.options-common-server-specific.openldap.table">
  603. <title>Options for OpenLDAP</title>
  604. <tgroup cols="2">
  605. <thead>
  606. <row>
  607. <entry>Name</entry>
  608. <entry>Additional Notes</entry>
  609. </row>
  610. </thead>
  611. <tbody>
  612. <row>
  613. <entry><emphasis>host</emphasis></entry>
  614. <entry>
  615. As with all servers, this option is required.
  616. </entry>
  617. </row>
  618. <row>
  619. <entry><emphasis>useStartTls</emphasis></entry>
  620. <entry>
  621. For the sake of security, this should be <constant>TRUE</constant>
  622. if the server has the necessary certificate installed.
  623. </entry>
  624. </row>
  625. <row>
  626. <entry><emphasis>useSsl</emphasis></entry>
  627. <entry>
  628. Possibly used as an alternative to <emphasis>useStartTls</emphasis>
  629. (see above).
  630. </entry>
  631. </row>
  632. <row>
  633. <entry><emphasis>username</emphasis></entry>
  634. <entry>
  635. Required and must be a DN, as OpenLDAP requires that usernames be
  636. in DN form when performing a bind. Try to use an unprivileged
  637. account.
  638. </entry>
  639. </row>
  640. <row>
  641. <entry><emphasis>password</emphasis></entry>
  642. <entry>
  643. The password corresponding to the username above, but this may be
  644. omitted if the <acronym>LDAP</acronym> server permits an anonymous
  645. binding to query user accounts.
  646. </entry>
  647. </row>
  648. <row>
  649. <entry><emphasis>bindRequiresDn</emphasis></entry>
  650. <entry>
  651. Required and must be <constant>TRUE</constant>, as OpenLDAP
  652. requires that usernames be in DN form when performing a bind.
  653. </entry>
  654. </row>
  655. <row>
  656. <entry><emphasis>baseDn</emphasis></entry>
  657. <entry>
  658. As with all servers, this option is required and indicates the DN
  659. under which all accounts being authenticated are located.
  660. </entry>
  661. </row>
  662. <row>
  663. <entry><emphasis>accountCanonicalForm</emphasis></entry>
  664. <entry>
  665. Optional, but the default value is 4 (principal style names like
  666. <filename>alice@foo.net</filename>), which may not be ideal if your
  667. users are used to backslash style names (e.g.,
  668. <filename>FOO\alice</filename>). For backslash style names use
  669. value 3.
  670. </entry>
  671. </row>
  672. <row>
  673. <entry><emphasis>accountDomainName</emphasis></entry>
  674. <entry>
  675. Required unless you're using
  676. <emphasis>accountCanonicalForm</emphasis> 2, which is not
  677. recommended.
  678. </entry>
  679. </row>
  680. <row>
  681. <entry><emphasis>accountDomainNameShort</emphasis></entry>
  682. <entry>
  683. If AD is not also being used, this value is not required.
  684. Otherwise, if <emphasis>accountCanonicalForm</emphasis> 3 is used,
  685. this option is required and should be a short name that corresponds
  686. adequately to the <emphasis>accountDomainName</emphasis> (e.g., if
  687. your <emphasis>accountDomainName</emphasis> is
  688. <filename>foo.net</filename>, a good
  689. <emphasis>accountDomainNameShort</emphasis> value might be
  690. <acronym>FOO</acronym>).
  691. </entry>
  692. </row>
  693. </tbody>
  694. </tgroup>
  695. </table>
  696. </sect3>
  697. </sect2>
  698. </sect1>
  699. <!--
  700. vim:se ts=4 sw=4 et:
  701. -->