Wiki source code of Authentication

Version 31.1 by Thomas Mortagne on 2010/01/20

Show last authors
1 1 User Authentication
2
3 XWiki supports several different authentication mechanisms for authenticating users:
4 #toc("" "" "")
5
6 The form authentication is the default mechanism.
7
8 #info("Note that currently XWiki allows only one method of authentication to be enabled at a time. This will probably be improved in the future.")
9
10 1.1 Form Authentication
11
12 TODO
13
14 1.1 LDAP Authentication
15
16 #warning("New LDAP implementation since XWiki Platform 1.3M2, see [previous LDAP authentication service documentation>AuthenticationLdapOld]")
17
18 1.1.1 Generic LDAP configuration
19
20 In order to enable the LDAP support you have to change the authentication method in ~~WEB-INF/xwiki.cfg~~ as follows:
21 {code}
22 ## Turn LDAP authentication on - otherwise only XWiki authentication
23 ## 0 : disable
24 ## 1 : enable
25 xwiki.authentication.ldap=1
26
27 ## set LDAP as authentication service
28 xwiki.authentication.authclass=com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl
29
30 {code}
31
32 You can setup the LDAP configuration in the ~~xwiki.cfg~~ file by filling the following properties:
33
34 {code:none}
35 ## LDAP Server (Active Directory, eDirectory, OpenLDAP, etc.)
36 xwiki.authentication.ldap.server=156.58.101.204
37 xwiki.authentication.ldap.port=389
38
39 ## LDAP login, empty = anonymous access, otherwise specify full dn
40 ## {0} is replaced with the username, {1} with the password
41 xwiki.authentication.ldap.bind_DN=cn={0},department=USER,department=INFORMATIK,department=1230,o=MP
42 xwiki.authentication.ldap.bind_pass={1}
43
44 ## Force to check password after LDAP connection
45 ## 0: disable
46 ## 1: enable
47 xwiki.authentication.ldap.validate_password=0
48
49 ## only members of the following group will be verified in the LDAP
50 ## otherwise only users that are found after searching starting from the base_DN
51 xwiki.authentication.ldap.user_group=cn=developers,ou=groups,o=MegaNova,c=US
52
53 ## only users not member of the following group can autheticate
54 xwiki.authentication.ldap.exclude_group=cn=admin,ou=groups,o=MegaNova,c=US
55
56 ## base DN for searches
57 xwiki.authentication.ldap.base_DN=
58 department=USER,department=INFORMATIK,department=1230,o=MP
59
60 ## specifies the LDAP attribute containing the identifier to be used as the XWiki name (default=cn)
61 xwiki.authentication.ldap.UID_attr=cn
62
63 ## retrieve the following fields from LDAP and store them in the XWiki user object (xwiki-attribute=ldap-attribute)
64 xwiki.authentication.ldap.fields_mapping=last_name=sn,first_name=givenName,fullname=fullName,email=mail
65
66 # on every login update the mapped attributes from LDAP to XWiki otherwise this happens only once when the XWiki account is created.
67 xwiki.authentication.ldap.update_user=1
68
69 ## maps XWiki groups to LDAP groups, separator is "|"
70 xwiki.authentication.ldap.group_mapping=XWiki.XWikiAdminGroup=cn=AdminRole,ou=groups,o=MegaNova,c=US|\
71 XWiki.Organisation=cn=testers,ou=groups,o=MegaNova,c=US
72
73 ## time in seconds after which the list of members in a group is refreshed from LDAP (default=3600*6)
74 xwiki.authentication.ldap.groupcache_expiration=21800
75
76 ## - create : synchronize group membership only when the user is first created
77 ## - always: synchronize on every login
78 xwiki.authentication.ldap.mode_group_sync=always
79
80 ## if ldap authentication fails for any reason, try XWiki DB authentication with the same credentials
81 xwiki.authentication.ldap.trylocal=1
82
83 ## SSL connection to LDAP server
84 ## 0 : normal
85 ## 1 : SSL
86 xwiki.authentication.ldap.ssl=1
87
88 ## The keystore file to use in SSL connection
89 xwiki.authentication.ldap.ssl.keystore=
90 {code}
91
92 #info("You can also setup the LDAP configuration in XWiki.XWikiPreferences page by going to the object editor. Simply replace \"xwiki.authentication.ldap.\" by \"ldap_\". For example <tt>xwiki.authentication.ldap.base_DN</tt> become <tt>ldap_base_DN</tt>")
93
94 The bind_DN and bind_pass fields contain the username and password for binding to the LDAP server in order to search, which will not necessarily be the same credentials as the user logging in.
95
96 The exact details of this configuration will vary based on your server configuration. It may not be necessary to prefix the username (represented by {0}) with the subdomain.
97
98 For testing purposes, you may wish to omit the "ldap.fields_mapping" field, to test the authentication first, and then add it later to get the mappings right.
99
100 Here are some LDAP client for checking your configuration:
101 * This java client, [LDAP Browser/Editor > http://www-unix.mcs.anl.gov/~gawor/ldap/] is a handy tool for checking your configuration.
102 * [Apache Directory Studio>http://directory.apache.org/studio/]
103
104 1.1.1 Detailed use cases
105
106 See [LDAP configuration uses cases>LDAPAuthenticationUseCases] for some detailed use cases.
107
108 1.1.1 Enable LDAP debug log
109
110 See [AdminGuide.Logging]. The specific targets for LDAP authentication are:
111 {code}
112 log4j.logger.com.xpn.xwiki.plugin.ldap=debug
113 log4j.logger.com.xpn.xwiki.user.impl.LDAP=debug
114 {code}
115
116
117 1.1 eXo Authentication
118
119 The eXo authentication is used automatically by adding/editing the ~~xwiki.exo=1~~ property in ~~WEB-INF/xwiki.cfg~~.
120
121 1.1 Custom Authentication
122
123 This allows plugging to any existing authentication mechanism such as SiteMinder, etc. To configure a custom authentication do the following:
124 # Implement the [XWikiAuthService>http://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/user/api/XWikiAuthService.java] interface.
125 # Edit the ~~WEB-INF/xwiki.cfg~~ file and add a ~~xwiki.authentication.authclass~~ property pointing to your class. For example:
126
127 {code}
128 xwiki.authentication.authclass = com.acme.MyCustomAuthenticationService
129 {code}
130
131 Here's a [tutorial on implementing a custom authentication class for authenticating against Oracle's SSO>http://bodez.wordpress.com/2008/10/15/xwiki-user-authentication-with-oracle-sso/].
132
133 Note, that you also can implement own right management service by implementing [XWikiRightService>http://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/user/api/XWikiRightService.java] interface:
134 {code}
135 xwiki.authentication.rightsclass = com.acme.MyCustomRightsService
136 {code}
137
138 and Group Service by implementing [XWikiGroupService>http://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-core/src/main/java/com/xpn/xwiki/user/api/XWikiGroupService.java]:
139
140 {code}
141 xwiki.authentication.groupclass = com.acme.MyCustomGroupService
142 {code}
143
144 1.1.1 Custom Authentication using a Groovy script in a wiki page
145
146 Start by specifying you want to use the Groovy Authenticator:
147
148 {code}
149 xwiki.authentication.authclass = com.xpn.xwiki.user.impl.xwiki.GroovyAuthServiceImpl
150 {code}
151
152 Then add another configuration parameter to specify in which wiki page the authenticator is:
153
154 {code}
155 xwiki.authentication.groovy.pagename = MySpace.MyPage
156 {code}
157
158 Then in a wiki page put some Groovy code that returns a XWikiAuthService object.
159
160 1.1 Authentication parameters
161
162 You can set each of these parameters by setting:
163
164 {code}
165 xwiki.authentication.~~param_name~~=~~param_value~~
166 {code}
167
168 {table}
169 Name | Optional | Allowed values | Default value | Description
170 encryptionKey | No(1) | ? | n/a | Set the Encryption Key used to create a secret key, the secret key is passed to the Cipher object to be used during encryption and decryption of cookie values.
171 validationKey | No(2) | ? | n/a | Set the Validation Key used to generate hash value; the hash value is stored with the cookie and used to verify that the cookie has not been tampered with.
172 cookiedomains | Yes | String | Server host name | Which host(s) should your cookies be sent to; use only if you want to share cookies across domains, otherwise should be commented out
173 cookielife | Yes | Number | 14 | Number of days cookies take to expire
174 cookiepath | Yes | String | / | The webapp path that XWiki cookies should be sent to; if you have anything else running on your web server, this should be set to ~~/xwiki~~
175 default_page | Yes | String | /bin/view/ Main/WebHome | Page to redirect to if xredirect parameter is not set
176 encryptionalgorithm | Yes | ? | ? | Set the Encryption Algorithm used to encrypt and decrypt cookies
177 encryptionmode | Yes | ? | ? | Set the Encryption Mode used to encrypt and decrypt cookies
178 encryptionpadding | Yes | ? | ? | Set the Encryption Padding used to encrypt and decrypt cookies
179 errorpage | Yes | String | /bin/loginerror/ XWiki/XWikiLogin | Page to redirect to if there is an error logging in
180 loginpage | Yes | String | /bin/login/ XWiki/XWikiLogin | Page to redirect to when not logged in
181 loginsubmitpage | Yes | String | /loginsubmit/ XWiki/XWikiLogin | ?
182 logoutpage | Yes | String | /bin/logout/ XWiki/XWikiLogout | Page to redirect to after logged out
183 realmname | Yes | String | XWiki | Sets the realm name
184 protection | Yes | all, validation, encryption, none | all | Protection level for the "remember me" cookie functionality
185 unauthorized_code | Yes | ? | ? | ?
186 useip | Yes | true / false | true | Specify to use the IP address when encrypting the cookie data; if IP address changes will need to re-login.
187 {table}
188 # Only required if protection = encryption or all (default)
189 # Only required if protection = validation or all (default)
190
191 1.1 Kerberos SSO Authentication
192
193 #warning("This implementation of SSO is currently under review see: http://jira.xwiki.org/jira/browse/XWIKI-2496 . The class which is described in this segment of documentation, AppServerTrustedKerberosAuthServiceImpl, is not part of the default XWiki distribution!")
194
195 The following is an example of mod_auth_kerb for Apache being used to easily implement Xwiki authentication of users via by HTTP Negotiate on a linux server. This example assumes you already have a working Apache2 HTTPD and Apache Tomcat setup with mod_jk.
196
197 First of all you need to create a principal and keytab for the webserver:
198 {code}
199 # kadmin
200 kadmin> addprinc -randkey HTTP/wiki.example.com
201 kadmin> ktadd -k /etc/apache2/ssl/wiki.keytab HTTP/wiki.example.com
202 kadmin> quit
203 {code}
204
205 Make sure the keytab has the right permissions and ownership:
206 {code}
207 chown www-data:www-data /etc/apache2/ssl/wiki.keytab
208 chmod 400 /etc/apache2/ssl/wiki.keytab
209 {code}
210
211 Install mod_auth_kerb in your linux installation. On Debian or Ubuntu this would be achieved by running:
212 {code}
213 aptitude install libapache2-mod-auth-kerb
214 {code}
215 Of course the installation procedure varies per Linux distribution.
216
217 If your xwiki installation is mounted in Apache HTTPD under /xwiki, add the following to the virtual host configuration:
218 {code}
219 <Location /xwiki/>
220 AuthType Kerberos
221 AuthName "Kerberos Login"
222 KrbAuthRealms EXAMPLE.COM
223 Krb5Keytab "/etc/apache2/ssl/wiki.keytab"
224 KrbMethodK5Passwd off
225 KrbMethodNegotiate on
226 KrbSaveCredentials on
227 require valid-user
228 </Location>
229 {code}
230
231 Make sure Apache Tomcat uses the authentication performed by Apache HTTPD with the "tomcatAuthentication" property in the connector description (which is in the server.xml file of Apache Tomcat):
232 {code}
233 <Connector port="8009" address="127.0.0.1" enableLookups="false" tomcatAuthentication="false" redirectPort="8443" protocol="AJP/1.3" />
234 {code}
235
236 Place the authkerb.jar jar in the WEB-INF/lib directory of Xwiki in Apache Tomcat.
237
238 Have Xwiki use the authentication module by changing the "xwiki.authentication.authclass" property in WEB-INF/lib/xwiki.cfg file.
239 {code}
240 xwiki.authentication.authclass=com.xpn.xwiki.user.impl.xwiki.AppServerTrustedKerberosAuthServiceImpl
241 {code}
242
243 If you use Firefox, do not forget to whitelist the xwiki URL for HTTP Negotiate in about:config with the "network.negotiate-auth.trusted-uris" property. possible values for this propperty include (without the quotes): "https://" for all secured connections or "example.com" for all example.com subdomains.
244
245
246
247 2 JBoss SPNEGO (Kerberos in combination with LDAP)
248 I changed the code of the XWikiLDAPAuthServiceImpl to be able to detect the sso user.
249 The authenication already happend by using the SPNEGO module (JAAS).
250 After that I'm using the ldap synchronisation feature to make sure that the user is up to date.
251 The combination leads to an automatic login in the xwiki and the user rights are controlled in the Active Directory server.
252 I hope you can adopt this code or that you can use it for your own projects.
253
254 The configuration of ldap;
255 {code}
256 xwiki.authentication.authclass=com.wiki.sso.SSOLdapAuthenicationImpl
257 xwiki.authentication.ldap=1
258 xwiki.authentication.ldap.server=<ad-server>
259 xwiki.authentication.ldap.port=389
260 xwiki.authentication.ldap.base_DN=<OU=Users,...............>
261 #use a fixed user to attach to the ldap database,
262 #the password is not provided with the SSOLdapAuthenicationImpl
263 xwiki.authentication.ldap.bind_DN=<domain>\\<user>
264 xwiki.authentication.ldap.bind_pass=<password>
265 #Microsoft AD configuration
266 xwiki.authentication.ldap.UID_attr=sAMAccountName
267 xwiki.authentication.ldap.fields_mapping=name=sAMAccountName,last_name=sn,first_name=givenName,fullname=displayName,mail=mail,ldap_dn=dn
268 xwiki.authentication.ldap.group_memberfields=member,uniqueMember
269 #LDAP group mapping
270 xwiki.authentication.ldap.group_mapping=XWiki.XWikiAdminGroup=CN=WIKI_Admin,............|\
271 XWiki.XWikiAllGroup=CN=WIKI_User,...........
272
273 {code}
274 The java code
275 {code}
276 package com.wiki.sso;
277
278
279 import org.apache.commons.logging.Log;
280 import org.apache.commons.logging.LogFactory;
281
282 import com.xpn.xwiki.XWikiContext;
283 import com.xpn.xwiki.XWikiException;
284 import com.xpn.xwiki.user.api.XWikiUser;
285 import com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl;
286
287 import java.security.Principal;
288
289 public class SSOLdapAuthenicationImpl extends XWikiLDAPAuthServiceImpl {
290 /**
291 * Logging tool.
292 */
293 private static final Log LOG = LogFactory.getLog(SSOLdapAuthenicationImpl.class);
294
295
296 public XWikiUser checkAuth(XWikiContext context) throws XWikiException {
297 String user = getRemoteUser(context);
298 if ((user != null) || !user.equals("")) {
299 if (LOG.isInfoEnabled())
300 LOG.info("Launching create user for " + user);
301 if ( authenticate(user, context) != null ) {
302 if (LOG.isInfoEnabled())
303 LOG.info("Create user done for " + user);
304 user = "XWiki." + user;
305 context.setUser(user);
306 System.out.println("User is set to:" + user);
307 return new XWikiUser(user);
308 } else {
309 LOG.error( "User " + user + " can't be authenticated against ldap" );
310 }
311 }
312 return super.checkAuth(context);
313 }
314
315 /**
316 * We cannot authenticate locally since we need to trust the app server for
317 * authentication
318 *
319 * @param username
320 * @param password
321 * @param context
322 * @return
323 * @throws XWikiException
324 */
325 public XWikiUser checkAuth(String username, String password,
326 String rememberme, XWikiContext context) throws XWikiException {
327 String user = getRemoteUser(context);
328 if ((user == null) || user.equals("")) {
329 return super.checkAuth(username, password, rememberme, context);
330 }
331 return checkAuth(context);
332 }
333
334 private String getRemoteUser(XWikiContext context) {
335 String userName = context.getRequest().getHttpServletRequest()
336 .getRemoteUser();
337 if (userName != null) {
338 // only take the front of the username@domain
339 String[] elements = userName.split("@", 2);
340 userName = elements[0];
341 }
342 return userName;
343 }
344
345 public Principal authenticate(String login, XWikiContext context) throws XWikiException
346 {
347 if (LOG.isTraceEnabled()) {
348 LOG.trace("Starting LDAP authentication");
349 }
350
351 /*
352 * TODO: Put the next 4 following "if" in common with XWikiAuthService to ensure coherence This method was
353 * returning null on failure so I preserved that behaviour, while adding the exact error messages to the context
354 * given as argument. However, the right way to do this would probably be to throw XWikiException-s.
355 */
356
357 if (login == null) {
358 // If we can't find the username field then we are probably on the login screen
359
360 if (LOG.isDebugEnabled()) {
361 LOG.debug("The provided user is null."
362 + " We don't try to authenticate, it probably means the user is in non logged mode.");
363 }
364
365 return null;
366 }
367
368 // Check for empty usernames
369 if (login.equals("")) {
370 context.put("message", "nousername");
371
372 if (LOG.isDebugEnabled()) {
373 LOG.debug("LDAP authentication failed: login empty");
374 }
375
376 return null;
377 }
378
379 // If we have the context then we are using direct mode
380 // then we should specify the database
381 // This is needed for virtual mode to work
382 Principal principal = null;
383
384 // Try authentication against ldap
385 principal = ldapAuthenticate(login, "", context);
386
387 if (LOG.isDebugEnabled()) {
388 if (principal != null) {
389 LOG.debug("LDAP authentication succeed with principal [" + principal.getName() + "]");
390 } else {
391 LOG.debug("LDAP authentication failed for user [" + login + "]");
392 }
393 }
394
395 return principal;
396 }
397 }
398 {code}

Get Connected