mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

maximthomas
02.10.2024 989a3319425a5e032c32a14e83c2aa4b8795f9e0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! You can also obtain a copy of the license at
  ! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright 2011-2012 ForgeRock AS
  !    
-->
<chapter xml:id='chap-authenticating'
 xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd'
 xmlns:xlink='http://www.w3.org/1999/xlink'
 xmlns:xinclude='http://www.w3.org/2001/XInclude'>
 <title>Authenticating To the Directory</title>
 
 <para>When your client application connects to the directory, the first
 operation to perform is a bind operation. The bind operation authenticates
 the client to the directory.</para>
 
 <section xml:id="simple-auth">
  <title>Simple Authentication</title>
  <indexterm>
   <primary>Authentications</primary>
   <secondary>Simple</secondary>
  </indexterm>
 
  <para>You perform simple authentication by binding with the distinguished
  name of a user's directory entry and the user's password. For this reason
  simple authentication over unsecure network connections should be done only
  in the lab. If your real end users are providing their passwords, your
  application must use simple authentication only if the network is
  secure.</para>
  
  <para>To bind using Barbara Jensen's identity and simple authentication,
  for example, your application would provide the DN
  <literal>uid=bjensen,ou=People,dc=example,dc=com</literal> with the
  password <literal>hifalutin</literal>.</para>
  
  <para>The directory stores the password value used for simple authentication
  in binary form on the <literal>userPassword</literal> attribute of the entry.
  In other words, for the purposes of your application the password is not a
  string, but instead an array of bytes. Typically the directory is further
  configured to store only hashed values of user passwords, rather than plain
  text versions. Thus even if someone managed to read the stored password
  values, they would still have to crack the hash in order to learn the
  actual passwords. When your application performing simple authentication
  sends the password value, the directory server therefore hashes the password
  value, and then compares the hashed result with the value of the
  <literal>userPassword</literal> on the user entry. If the values match,
  then the directory authenticates the user. Once the user has authenticated,
  the directory determines authorization for operations on the connection
  based on the users identity.</para>
  
  <programlisting language="java">
/**
 * Authenticate over LDAP.
 */
private static void connect()
{
  final LDAPConnectionFactory factory = new LDAPConnectionFactory(
    host, port);
  Connection connection = null;
 
  try
  {
    connection = factory.getConnection();
    connection.bind(bindDN, bindPassword.toCharArray());
    System.out.println("Authenticated as " + bindDN + ".");
  }
  catch (final ErrorResultException e)
  {
    System.err.println(e.getMessage());
    System.exit(e.getResult().getResultCode().intValue());
    return;
  }
  finally
  {
    if (connection != null) connection.close();
  }
}</programlisting>
  
  <para>If the password values do not match, a directory might nevertheless
  authenticate the client application. The LDAP specifications say that in this
  case, however, the directory authenticates the user as anonymous, therefore
  no doubt with fewer rights than the normal user, and surely fewer rights
  than an administrator.</para>
 
  <para>For a complete example in context, see <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/SimpleAuth.html"
  xlink:show="new">SimpleAuth.java</link>, one of the <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/"
  xlink:show="new">OpenDJ LDAP SDK examples</link>.</para>
 </section>
 
 <section xml:id="simple-auth-with-starttls-or-ssl">
  <title>Start TLS &amp; SSL Authentication</title>
  <indexterm>
   <primary>Authentications</primary>
   <secondary>StartTLS, SSL</secondary>
  </indexterm>
  <indexterm>
   <primary>Extended operations</primary>
   <secondary>StartTLS</secondary>
  </indexterm>
 
  <para>Simple authentication involves sending a user name and password to
  the directory server. To avoid sending the user name and password in
  the clear, you can use SSL or Start TLS.</para>
  
  <para>For both SSL and Start TLS, you pass LDAP options to the connection
  factory in order to set an SSL context, and set whether to use Start TLS.
  The SSL context lets you set a trust manager to check server certificates,
  and also set a key manager to provide keys when the server needs to check
  your client certificates. In the simplest, not-so-secure case, you can
  set up a trust manager that trusts all certificates.</para>
  
  <para>The following example is an excerpt from the OpenDJ LDAP SDK example,
  <filename>org.forgerock.opendj.examples.SimpleAuth.java</filename>.</para>
  
  <programlisting language="java">
private static LDAPOptions getTrustAllOptions()
  throws GeneralSecurityException
{
  LDAPOptions lo = new LDAPOptions();
  SSLContext sslContext = new SSLContextBuilder()
    .setTrustManager(TrustManagers.trustAll()).getSSLContext();
  lo.setSSLContext(sslContext);
  lo.setUseStartTLS(useStartTLS);
  return lo;
}</programlisting>
  
  <para>A more secure and extensive SSL context would include a trust manager
  using a trust store and trust manager methods to check server certificates.
  If you also want to be able to authenticate to the server using your client
  certificate, you would need a key manager.</para>
  
  <para>The authentication over SSL or using Start TLS in the trust-all case is
  much like simple authentication over LDAP without connection-level security.
  The primary differences are that you pass the <literal>LDAPOptions</literal>
  to the LDAP connection factory, and that you handle the potential security
  exception involved in setting up the SSL context.</para>
  
  <programlisting language="java">
/**
 * Perform authentication over a secure connection, trusting all server
 * certificates.
 */
private static void trustAllConnect()
{
  Connection connection = null;
 
  try
  {
    final LDAPConnectionFactory factory =
        new LDAPConnectionFactory(host, port, getTrustAllOptions());
    connection = factory.getConnection();
    connection.bind(bindDN, bindPassword.toCharArray());
    System.out.println("Authenticated as " + bindDN + ".");
  }
  catch (final ErrorResultException e)
  {
    System.err.println(e.getMessage());
    System.exit(e.getResult().getResultCode().intValue());
    return;
  }
  catch (final GeneralSecurityException e)
  {
    System.err.println(e.getMessage());
    System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue());
  }
  finally
  {
    if (connection != null)
      connection.close();
  }
}</programlisting>
 
  <para>For a complete example in context, see <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/SimpleAuth.html"
  xlink:show="new">SimpleAuth.java</link>, one of the <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/"
  xlink:show="new">OpenDJ LDAP SDK examples</link>.</para>
 </section>
 
 <section xml:id="sasl-auth">
  <title>SASL Authentication</title>
  <indexterm>
   <primary>Authentications</primary>
   <secondary>SASL</secondary>
  </indexterm>
 
  <para>Simple Authentication and Security Layer (SASL) provides a way to
  use other mechanisms for authentication such as Kerberos or Digest
  authentication, or even to define your own authentication mechanism. The
  directory server likely advertises supported SASL mechanisms in the root
  DSE. The follow example shows how to search OpenDJ for supported SASL
  mechanisms.</para>
  
  <screen>$ ldapsearch
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --baseDN ""
 --searchScope base
 "(objectclass=*)" supportedSASLMechanisms
dn: 
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: EXTERNAL
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5</screen>
 
  <para>Notice that neither the Kerberos (GSSAPI SASL) nor the Anonymous
  mechanism is enabled by default, though OpenDJ implements both.</para>
  
  <para>In order to use a SASL mechanism to bind, your program must set up
  a <literal>SASLBindRequest</literal> and pass that to the
  <literal>bind()</literal> method of the <literal>Connection</literal>.</para>
  
  <para>This section shows an example using the SASL PLAIN mechanism, which
  takes either a DN or a user ID to authenticate, with an optional DN or user
  ID as the authorization ID that identifies the user who performs operations.
  The SASL PLAIN mechanism itself does not secure the connection, so the
  example uses StartTLS. The example is provided with the OpenDJ LDAP SDK
  examples in <filename>org.forgerock.opendj.examples.SASLAuth.java</filename>.
  The following excerpt shows the core of the bind process.</para>
  
  <programlisting language="java">
try
{
  final LDAPConnectionFactory factory =
      new LDAPConnectionFactory(host, port, getTrustAllOptions());
  connection = factory.getConnection();
  PlainSASLBindRequest request =
      Requests.newPlainSASLBindRequest(authcid, passwd.toCharArray())
      .setAuthorizationID(authzid);
  connection.bind(request);
  System.out.println("Authenticated as " + authcid + ".");
}</programlisting>
 
  <para>The implementation for <literal>getTrustAllOptions()</literal>, the
  same as in the example above, sets up Start TLS. When you run this example
  with both authorization and authentication IDs, <literal>authzid</literal>
  and <literal>authcid</literal>, set to <literal>u:bjensen</literal> and
  password <literal>hifalutin</literal>, the bind is successful, and the
  program reaches the final line of the <literal>try</literal> block.</para>
  
  <screen>Authenticated as u:bjensen.</screen>
  
  <para>Behind the scenes, OpenDJ has the SASL PLAIN mechanism configured by
  default to use the Exact Match Identity Mapper to look up user IDs as
  <literal>uid</literal> values. If you use another directory server, you might
  have to configure how it maps user IDs to user entries.</para>
 
  <para>For a complete example in context, see <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/SASLAuth.html"
  xlink:show="new">SASLAuth.java</link>, one of the <link
  xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/"
  xlink:show="new">OpenDJ LDAP SDK examples</link>.</para>
 </section>
</chapter>