Zend_Auth_Adapter_Ldap.xml 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  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. <property>bindRequiresDn</property> 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><property>host</property></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><property>port</property></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. <property>port</property> value is 636. If <property>useSsl</property>
  257. is <constant>FALSE</constant>, the default <property>port</property>
  258. value is 389.
  259. </entry>
  260. </row>
  261. <row>
  262. <entry><emphasis><property>useStartTls</property></emphasis></entry>
  263. <entry>
  264. Whether or not the <acronym>LDAP</acronym> client should use
  265. <acronym>TLS</acronym> (aka <acronym>SSL</acronym>v2) encrypted
  266. transport. A value of <constant>TRUE</constant> is strongly favored in
  267. production environments to prevent passwords from be transmitted in
  268. clear text. The default value is <constant>FALSE</constant>, as servers
  269. frequently require that a certificate be installed separately after
  270. installation. The <property>useSsl</property> and
  271. <property>useStartTls</property> options are mutually exclusive. The
  272. <property>useStartTls</property> option should be favored over
  273. <property>useSsl</property> but not all servers support this newer
  274. mechanism.
  275. </entry>
  276. </row>
  277. <row>
  278. <entry><emphasis><property>useSsl</property></emphasis></entry>
  279. <entry>
  280. Whether or not the <acronym>LDAP</acronym> client should use
  281. <acronym>SSL</acronym> encrypted transport. The
  282. <property>useSsl</property> and <property>useStartTls</property>
  283. options are mutually exclusive, but <property>useStartTls</property>
  284. should be favored if the server and <acronym>LDAP</acronym> client
  285. library support it. This value also changes the default
  286. <property>port</property> value (see <property>port</property>
  287. description above).
  288. </entry>
  289. </row>
  290. <row>
  291. <entry><emphasis><property>username</property></emphasis></entry>
  292. <entry>
  293. The DN of the account used to perform account DN lookups.
  294. <acronym>LDAP</acronym> servers that require the username to be in DN
  295. form when performing the "bind" require this option. Meaning, if
  296. <property>bindRequiresDn</property> is <constant>TRUE</constant>, this
  297. option is required. This account does not need to be a privileged
  298. account; an account with read-only access to objects under the
  299. <property>baseDn</property> is all that is necessary (and preferred
  300. based on the <emphasis>Principle of Least Privilege</emphasis>).
  301. </entry>
  302. </row>
  303. <row>
  304. <entry><emphasis><property>password</property></emphasis></entry>
  305. <entry>
  306. The password of the account used to perform account DN lookups. If this
  307. option is not supplied, the <acronym>LDAP</acronym> client will attempt
  308. an "anonymous bind" when performing account DN lookups.
  309. </entry>
  310. </row>
  311. <row>
  312. <entry><emphasis><property>bindRequiresDn</property></emphasis></entry>
  313. <entry>
  314. Some <acronym>LDAP</acronym> servers require that the username used to
  315. bind be in DN form like
  316. <emphasis>CN=Alice Baker,OU=Sales,DC=foo,DC=net</emphasis> (basically
  317. all servers <emphasis>except</emphasis> AD). If this option is
  318. <constant>TRUE</constant>, this instructs
  319. <classname>Zend_Ldap</classname> to automatically retrieve the DN
  320. corresponding to the username being authenticated, if it is not already
  321. in DN form, and then re-bind with the proper DN. The default value is
  322. <constant>FALSE</constant>. Currently only Microsoft Active Directory
  323. Server (<acronym>ADS</acronym>) is known <emphasis>not</emphasis> to
  324. require usernames to be in DN form when binding, and therefore this
  325. option may be <constant>FALSE</constant> with AD (and it should be, as
  326. retrieving the DN requires an extra round trip to the server).
  327. Otherwise, this option must be set to <constant>TRUE</constant> (e.g.
  328. for OpenLDAP). This option also controls the default
  329. <property>acountFilterFormat</property> used when searching for
  330. accounts. See the <property>accountFilterFormat</property> option.
  331. </entry>
  332. </row>
  333. <row>
  334. <entry><emphasis><property>baseDn</property></emphasis></entry>
  335. <entry>
  336. The DN under which all accounts being authenticated are located. This
  337. option is required. if you are uncertain about the correct
  338. <property>baseDn</property> value, it should be sufficient to derive it
  339. from the user's <acronym>DNS</acronym> domain using
  340. <emphasis>DC=</emphasis> components. For example, if the user's
  341. principal name is <filename>alice@foo.net</filename>, a
  342. <property>baseDn</property> of <emphasis>DC=foo,DC=net</emphasis>
  343. should work. A more precise location (e.g.,
  344. <emphasis>OU=Sales,DC=foo,DC=net</emphasis>) will be more efficient,
  345. however.
  346. </entry>
  347. </row>
  348. <row>
  349. <entry>
  350. <emphasis><property>accountCanonicalForm</property></emphasis>
  351. </entry>
  352. <entry>
  353. A value of 2, 3 or 4 indicating the form to which account names should
  354. be canonicalized after successful authentication. Values are as
  355. follows: 2 for traditional username style names (e.g.,
  356. <emphasis>alice</emphasis>), 3 for backslash-style names (e.g.,
  357. <filename>FOO\alice</filename>) or 4 for principal style usernames
  358. (e.g., <filename>alice@foo.net</filename>). The default value is 4
  359. (e.g., <filename>alice@foo.net</filename>). For example, with a value
  360. of 3, the identity returned by
  361. <methodname>Zend_Auth_Result::getIdentity()</methodname> (and
  362. <methodname>Zend_Auth::getIdentity()</methodname>, if
  363. <classname>Zend_Auth</classname> was used) will always be
  364. <filename>FOO\alice</filename>, regardless of what form Alice supplied,
  365. whether it be <emphasis>alice</emphasis>,
  366. <filename>alice@foo.net</filename>, <filename>FOO\alice</filename>,
  367. <filename>FoO\aLicE</filename>, <filename>foo.net\alice</filename>,
  368. etc. See the <emphasis>Account Name Canonicalization</emphasis> section
  369. in the <classname>Zend_Ldap</classname> documentation for details. Note
  370. that when using multiple sets of server options it is recommended, but
  371. not required, that the same <property>accountCanonicalForm</property>
  372. be used with all server options so that the resulting usernames are
  373. always canonicalized to the same form (e.g., if you canonicalize to
  374. <filename>EXAMPLE\username</filename> with an AD server but to
  375. <filename>username@example.com</filename> with an OpenLDAP server, that
  376. may be awkward for the application's high-level logic).
  377. </entry>
  378. </row>
  379. <row>
  380. <entry><emphasis><property>accountDomainName</property></emphasis></entry>
  381. <entry>
  382. The <acronym>FQDN</acronym> domain name for which the target
  383. <acronym>LDAP</acronym> server is an authority (e.g.,
  384. <filename>example.com</filename>). This option is used to canonicalize
  385. names so that the username supplied by the user can be converted as
  386. necessary for binding. It is also used to determine if the server is an
  387. authority for the supplied username (e.g., if
  388. <property>accountDomainName</property> is <filename>foo.net</filename>
  389. and the user supplies <filename>bob@bar.net</filename>, the server will
  390. not be queried, and a failure will result). This option is not
  391. required, but if it is not supplied, usernames in principal name form
  392. (e.g., <filename>alice@foo.net</filename>) are not supported. It is
  393. strongly recommended that you supply this option, as there are many
  394. use-cases that require generating the principal name form.
  395. </entry>
  396. </row>
  397. <row>
  398. <entry>
  399. <emphasis><property>accountDomainNameShort</property></emphasis>
  400. </entry>
  401. <entry>
  402. The 'short' domain for which the target <acronym>LDAP</acronym> server
  403. is an authority (e.g., <acronym>FOO</acronym>). Note that there is a
  404. 1:1 mapping between the <property>accountDomainName</property> and
  405. <property>accountDomainNameShort</property>. This option should be used
  406. to specify the NetBIOS domain name for Windows networks, but may also
  407. be used by non-AD servers (e.g., for consistency when multiple sets of
  408. server options with the backslash style
  409. <property>accountCanonicalForm</property>). This option is not required
  410. but if it is not supplied, usernames in backslash form (e.g.,
  411. <filename>FOO\alice</filename>) are not supported.
  412. </entry>
  413. </row>
  414. <row>
  415. <entry><emphasis><property>accountFilterFormat</property></emphasis></entry>
  416. <entry>
  417. The <acronym>LDAP</acronym> search filter used to search for accounts.
  418. This string is a <ulink
  419. url="http://php.net/printf"><methodname>printf()</methodname></ulink>-style
  420. expression that must contain one '<emphasis>%s</emphasis>' to
  421. accomodate the username. The default value is
  422. '<emphasis>(&amp;(objectClass=user)(sAMAccountName=%s))</emphasis>',
  423. unless <property>bindRequiresDn</property> is set to
  424. <constant>TRUE</constant>, in which case the default is
  425. '<emphasis>(&amp;(objectClass=posixAccount)(uid=%s))</emphasis>'. For
  426. example, if for some reason you wanted to use
  427. <emphasis>bindRequiresDn = true</emphasis> with AD you would need to
  428. set <emphasis>accountFilterFormat =
  429. '(&amp;(objectClass=user)(sAMAccountName=%s))</emphasis>'.
  430. </entry>
  431. </row>
  432. <row>
  433. <entry><emphasis><property>optReferrals</property></emphasis></entry>
  434. <entry>
  435. If set to <constant>TRUE</constant>, this option indicates to the
  436. <acronym>LDAP</acronym> client that referrals should be followed. The
  437. default value is <constant>FALSE</constant>.
  438. </entry>
  439. </row>
  440. </tbody>
  441. </tgroup>
  442. </table>
  443. <note>
  444. <para>
  445. If you enable <emphasis>useStartTls = <constant>TRUE</constant></emphasis> or
  446. <emphasis>useSsl = <constant>TRUE</constant></emphasis> you may find that the
  447. <acronym>LDAP</acronym> client generates an error claiming that it cannot validate
  448. the server's certificate. Assuming the <acronym>PHP</acronym>
  449. <acronym>LDAP</acronym> extension is ultimately linked to the OpenLDAP client
  450. libraries, to resolve this issue you can set "<command>TLS_REQCERT never</command>"
  451. in the OpenLDAP client <filename>ldap.conf</filename> (and restart the web server)
  452. to indicate to the OpenLDAP client library that you trust the server. Alternatively,
  453. if you are concerned that the server could be spoofed, you can export the
  454. <acronym>LDAP</acronym> server's root certificate and put it on the web server so
  455. that the OpenLDAP client can validate the server's identity.
  456. </para>
  457. </note>
  458. </sect2>
  459. <sect2 id="zend.auth.adapter.ldap.debugging">
  460. <title>Collecting Debugging Messages</title>
  461. <para>
  462. <classname>Zend_Auth_Adapter_Ldap</classname> collects debugging information within its
  463. <methodname>authenticate()</methodname> method. This information is stored in the
  464. <classname>Zend_Auth_Result</classname> object as messages. The array returned by
  465. <methodname>Zend_Auth_Result::getMessages()</methodname> is described as follows
  466. </para>
  467. <table id="zend.auth.adapter.ldap.debugging.table">
  468. <title>Debugging Messages</title>
  469. <tgroup cols="2">
  470. <thead>
  471. <row>
  472. <entry>Messages Array Index</entry>
  473. <entry>Description</entry>
  474. </row>
  475. </thead>
  476. <tbody>
  477. <row>
  478. <entry>Index 0</entry>
  479. <entry>
  480. A generic, user-friendly message that is suitable for displaying to
  481. users (e.g., "Invalid credentials"). If the authentication is
  482. successful, this string is empty.
  483. </entry>
  484. </row>
  485. <row>
  486. <entry>Index 1</entry>
  487. <entry>
  488. A more detailed error message that is not suitable to be displayed to
  489. users but should be logged for the benefit of server operators. If the
  490. authentication is successful, this string is empty.
  491. </entry>
  492. </row>
  493. <row>
  494. <entry>Indexes 2 and higher</entry>
  495. <entry>All log messages in order starting at index 2.</entry>
  496. </row>
  497. </tbody>
  498. </tgroup>
  499. </table>
  500. <para>
  501. In practice, index 0 should be displayed to the user (e.g., using the FlashMessenger
  502. helper), index 1 should be logged and, if debugging information is being collected,
  503. indexes 2 and higher could be logged as well (although the final message always includes
  504. the string from index 1).
  505. </para>
  506. </sect2>
  507. <sect2 id="zend.auth.adapter.ldap.options-common-server-specific">
  508. <title>Common Options for Specific Servers</title>
  509. <sect3 id="zend.auth.adapter.ldap.options-common-server-specific.active-directory">
  510. <title>Options for Active Directory</title>
  511. <para>
  512. For <acronym>ADS</acronym>, the following options are noteworthy:
  513. </para>
  514. <table
  515. id="zend.auth.adapter.ldap.options-common-server-specific.active-directory.table">
  516. <title>Options for Active Directory</title>
  517. <tgroup cols="2">
  518. <thead>
  519. <row>
  520. <entry>Name</entry>
  521. <entry>Additional Notes</entry>
  522. </row>
  523. </thead>
  524. <tbody>
  525. <row>
  526. <entry><emphasis><property>host</property></emphasis></entry>
  527. <entry>As with all servers, this option is required.</entry>
  528. </row>
  529. <row>
  530. <entry><emphasis><property>useStartTls</property></emphasis></entry>
  531. <entry>
  532. For the sake of security, this should be <constant>TRUE</constant>
  533. if the server has the necessary certificate installed.
  534. </entry>
  535. </row>
  536. <row>
  537. <entry><emphasis><property>useSsl</property></emphasis></entry>
  538. <entry>
  539. Possibly used as an alternative to <emphasis>useStartTls</emphasis>
  540. (see above).
  541. </entry>
  542. </row>
  543. <row>
  544. <entry><emphasis><property>baseDn</property></emphasis></entry>
  545. <entry>
  546. As with all servers, this option is required. By default AD places
  547. all user accounts under the <emphasis>Users</emphasis> container
  548. (e.g., <emphasis>CN=Users,DC=foo,DC=net</emphasis>), but the
  549. default is not common in larger organizations. Ask your AD
  550. administrator what the best DN for accounts for your application
  551. would be.
  552. </entry>
  553. </row>
  554. <row>
  555. <entry>
  556. <emphasis><property>accountCanonicalForm</property></emphasis>
  557. </entry>
  558. <entry>
  559. You almost certainly want this to be 3 for backslash style names
  560. (e.g., <filename>FOO\alice</filename>), which are most familiar to
  561. Windows users. You should <emphasis>not</emphasis> use the
  562. unqualified form 2 (e.g., <emphasis>alice</emphasis>), as this may
  563. grant access to your application to users with the same username in
  564. other trusted domains (e.g., <filename>BAR\alice</filename> and
  565. <filename>FOO\alice</filename> will be treated as the same user).
  566. (See also note below.)
  567. </entry>
  568. </row>
  569. <row>
  570. <entry>
  571. <emphasis><property>accountDomainName</property></emphasis>
  572. </entry>
  573. <entry>
  574. This is required with AD unless
  575. <property>accountCanonicalForm</property> 2 is used, which, again,
  576. is discouraged.
  577. </entry>
  578. </row>
  579. <row>
  580. <entry>
  581. <emphasis><property>accountDomainNameShort</property></emphasis>
  582. </entry>
  583. <entry>
  584. The NetBIOS name of the domain that users are in and for which the
  585. AD server is an authority. This is required if the backslash style
  586. <property>accountCanonicalForm</property> is used.
  587. </entry>
  588. </row>
  589. </tbody>
  590. </tgroup>
  591. </table>
  592. <note>
  593. <para>
  594. Technically there should be no danger of accidental cross-domain authentication
  595. with the current <classname>Zend_Auth_Adapter_Ldap</classname> implementation,
  596. since server domains are explicitly checked, but this may not be true of a
  597. future implementation that discovers the domain at runtime, or if an alternative
  598. adapter is used (e.g., Kerberos). In general, account name ambiguity is known to
  599. be the source of security issues, so always try to use qualified account names.
  600. </para>
  601. </note>
  602. </sect3>
  603. <sect3 id="zend.auth.adapter.ldap.options-common-server-specific.openldap">
  604. <title>Options for OpenLDAP</title>
  605. <para>
  606. For OpenLDAP or a generic <acronym>LDAP</acronym> server using a typical
  607. posixAccount style schema, the following options are noteworthy:
  608. </para>
  609. <table id="zend.auth.adapter.ldap.options-common-server-specific.openldap.table">
  610. <title>Options for OpenLDAP</title>
  611. <tgroup cols="2">
  612. <thead>
  613. <row>
  614. <entry>Name</entry>
  615. <entry>Additional Notes</entry>
  616. </row>
  617. </thead>
  618. <tbody>
  619. <row>
  620. <entry><emphasis><property>host</property></emphasis></entry>
  621. <entry>As with all servers, this option is required.</entry>
  622. </row>
  623. <row>
  624. <entry><emphasis><property>useStartTls</property></emphasis></entry>
  625. <entry>
  626. For the sake of security, this should be <constant>TRUE</constant>
  627. if the server has the necessary certificate installed.
  628. </entry>
  629. </row>
  630. <row>
  631. <entry><emphasis><property>useSsl</property></emphasis></entry>
  632. <entry>
  633. Possibly used as an alternative to <property>useStartTls</property>
  634. (see above).
  635. </entry>
  636. </row>
  637. <row>
  638. <entry><emphasis><property>username</property></emphasis></entry>
  639. <entry>
  640. Required and must be a DN, as OpenLDAP requires that usernames be
  641. in DN form when performing a bind. Try to use an unprivileged
  642. account.
  643. </entry>
  644. </row>
  645. <row>
  646. <entry><emphasis><property>password</property></emphasis></entry>
  647. <entry>
  648. The password corresponding to the username above, but this may be
  649. omitted if the <acronym>LDAP</acronym> server permits an anonymous
  650. binding to query user accounts.
  651. </entry>
  652. </row>
  653. <row>
  654. <entry><emphasis><property>bindRequiresDn</property></emphasis></entry>
  655. <entry>
  656. Required and must be <constant>TRUE</constant>, as OpenLDAP
  657. requires that usernames be in DN form when performing a bind.
  658. </entry>
  659. </row>
  660. <row>
  661. <entry><emphasis><property>baseDn</property></emphasis></entry>
  662. <entry>
  663. As with all servers, this option is required and indicates the DN
  664. under which all accounts being authenticated are located.
  665. </entry>
  666. </row>
  667. <row>
  668. <entry>
  669. <emphasis><property>accountCanonicalForm</property></emphasis>
  670. </entry>
  671. <entry>
  672. Optional, but the default value is 4 (principal style names like
  673. <filename>alice@foo.net</filename>), which may not be ideal if your
  674. users are used to backslash style names (e.g.,
  675. <filename>FOO\alice</filename>). For backslash style names use
  676. value 3.
  677. </entry>
  678. </row>
  679. <row>
  680. <entry>
  681. <emphasis><property>accountDomainName</property></emphasis>
  682. </entry>
  683. <entry>
  684. Required unless you're using
  685. <property>accountCanonicalForm</property> 2, which is not
  686. recommended.
  687. </entry>
  688. </row>
  689. <row>
  690. <entry>
  691. <emphasis><property>accountDomainNameShort</property></emphasis>
  692. </entry>
  693. <entry>
  694. If AD is not also being used, this value is not required.
  695. Otherwise, if <property>accountCanonicalForm</property> 3 is used,
  696. this option is required and should be a short name that corresponds
  697. adequately to the <property>accountDomainName</property> (e.g., if
  698. your <property>accountDomainName</property> is
  699. <filename>foo.net</filename>, a good
  700. <property>accountDomainNameShort</property> value might be
  701. <acronym>FOO</acronym>).
  702. </entry>
  703. </row>
  704. </tbody>
  705. </tgroup>
  706. </table>
  707. </sect3>
  708. </sect2>
  709. </sect1>
  710. <!--
  711. vim:se ts=4 sw=4 et:
  712. -->