Wiki source code of Authentication

Version 32.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 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.
95
96 Here are some LDAP client for checking your configuration:
97 * This java client, [LDAP Browser/Editor > http://www-unix.mcs.anl.gov/~gawor/ldap/] is a handy tool for checking your configuration.
98 * [Apache Directory Studio>http://directory.apache.org/studio/]
99
100 1.1.1 Detailed use cases
101
102 See [LDAP configuration uses cases>LDAPAuthenticationUseCases] for some detailed use cases.
103
104 1.1.1 Enable LDAP debug log
105
106 See [AdminGuide.Logging]. The specific targets for LDAP authentication are:
107 {code}
108 log4j.logger.com.xpn.xwiki.plugin.ldap=debug
109 log4j.logger.com.xpn.xwiki.user.impl.LDAP=debug
110 {code}
111
112
113 1.1 eXo Authentication
114
115 The eXo authentication is used automatically by adding/editing the ~~xwiki.exo=1~~ property in ~~WEB-INF/xwiki.cfg~~.
116
117 1.1 Custom Authentication
118
119 This allows plugging to any existing authentication mechanism such as SiteMinder, etc. To configure a custom authentication do the following:
120 # 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.
121 # Edit the ~~WEB-INF/xwiki.cfg~~ file and add a ~~xwiki.authentication.authclass~~ property pointing to your class. For example:
122
123 {code}
124 xwiki.authentication.authclass = com.acme.MyCustomAuthenticationService
125 {code}
126
127 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/].
128
129 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:
130 {code}
131 xwiki.authentication.rightsclass = com.acme.MyCustomRightsService
132 {code}
133
134 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]:
135
136 {code}
137 xwiki.authentication.groupclass = com.acme.MyCustomGroupService
138 {code}
139
140 1.1.1 Custom Authentication using a Groovy script in a wiki page
141
142 Start by specifying you want to use the Groovy Authenticator:
143
144 {code}
145 xwiki.authentication.authclass = com.xpn.xwiki.user.impl.xwiki.GroovyAuthServiceImpl
146 {code}
147
148 Then add another configuration parameter to specify in which wiki page the authenticator is:
149
150 {code}
151 xwiki.authentication.groovy.pagename = MySpace.MyPage
152 {code}
153
154 Then in a wiki page put some Groovy code that returns a XWikiAuthService object.
155
156 1.1 Authentication parameters
157
158 You can set each of these parameters by setting:
159
160 {code}
161 xwiki.authentication.~~param_name~~=~~param_value~~
162 {code}
163
164 {table}
165 Name | Optional | Allowed values | Default value | Description
166 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.
167 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.
168 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
169 cookielife | Yes | Number | 14 | Number of days cookies take to expire
170 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~~
171 default_page | Yes | String | /bin/view/ Main/WebHome | Page to redirect to if xredirect parameter is not set
172 encryptionalgorithm | Yes | ? | ? | Set the Encryption Algorithm used to encrypt and decrypt cookies
173 encryptionmode | Yes | ? | ? | Set the Encryption Mode used to encrypt and decrypt cookies
174 encryptionpadding | Yes | ? | ? | Set the Encryption Padding used to encrypt and decrypt cookies
175 errorpage | Yes | String | /bin/loginerror/ XWiki/XWikiLogin | Page to redirect to if there is an error logging in
176 loginpage | Yes | String | /bin/login/ XWiki/XWikiLogin | Page to redirect to when not logged in
177 loginsubmitpage | Yes | String | /loginsubmit/ XWiki/XWikiLogin | ?
178 logoutpage | Yes | String | /bin/logout/ XWiki/XWikiLogout | Page to redirect to after logged out
179 realmname | Yes | String | XWiki | Sets the realm name
180 protection | Yes | all, validation, encryption, none | all | Protection level for the "remember me" cookie functionality
181 unauthorized_code | Yes | ? | ? | ?
182 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.
183 {table}
184 # Only required if protection = encryption or all (default)
185 # Only required if protection = validation or all (default)
186
187 1.1 Kerberos SSO Authentication
188
189 #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!")
190
191 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.
192
193 First of all you need to create a principal and keytab for the webserver:
194 {code}
195 # kadmin
196 kadmin> addprinc -randkey HTTP/wiki.example.com
197 kadmin> ktadd -k /etc/apache2/ssl/wiki.keytab HTTP/wiki.example.com
198 kadmin> quit
199 {code}
200
201 Make sure the keytab has the right permissions and ownership:
202 {code}
203 chown www-data:www-data /etc/apache2/ssl/wiki.keytab
204 chmod 400 /etc/apache2/ssl/wiki.keytab
205 {code}
206
207 Install mod_auth_kerb in your linux installation. On Debian or Ubuntu this would be achieved by running:
208 {code}
209 aptitude install libapache2-mod-auth-kerb
210 {code}
211 Of course the installation procedure varies per Linux distribution.
212
213 If your xwiki installation is mounted in Apache HTTPD under /xwiki, add the following to the virtual host configuration:
214 {code}
215 <Location /xwiki/>
216 AuthType Kerberos
217 AuthName "Kerberos Login"
218 KrbAuthRealms EXAMPLE.COM
219 Krb5Keytab "/etc/apache2/ssl/wiki.keytab"
220 KrbMethodK5Passwd off
221 KrbMethodNegotiate on
222 KrbSaveCredentials on
223 require valid-user
224 </Location>
225 {code}
226
227 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):
228 {code}
229 <Connector port="8009" address="127.0.0.1" enableLookups="false" tomcatAuthentication="false" redirectPort="8443" protocol="AJP/1.3" />
230 {code}
231
232 Place the authkerb.jar jar in the WEB-INF/lib directory of Xwiki in Apache Tomcat.
233
234 Have Xwiki use the authentication module by changing the "xwiki.authentication.authclass" property in WEB-INF/lib/xwiki.cfg file.
235 {code}
236 xwiki.authentication.authclass=com.xpn.xwiki.user.impl.xwiki.AppServerTrustedKerberosAuthServiceImpl
237 {code}
238
239 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.
240
241
242
243 2 JBoss SPNEGO (Kerberos in combination with LDAP)
244 I changed the code of the XWikiLDAPAuthServiceImpl to be able to detect the sso user.
245 The authenication already happend by using the SPNEGO module (JAAS).
246 After that I'm using the ldap synchronisation feature to make sure that the user is up to date.
247 The combination leads to an automatic login in the xwiki and the user rights are controlled in the Active Directory server.
248 I hope you can adopt this code or that you can use it for your own projects.
249
250 The configuration of ldap;
251 {code}
252 xwiki.authentication.authclass=com.wiki.sso.SSOLdapAuthenicationImpl
253 xwiki.authentication.ldap=1
254 xwiki.authentication.ldap.server=<ad-server>
255 xwiki.authentication.ldap.port=389
256 xwiki.authentication.ldap.base_DN=<OU=Users,...............>
257 #use a fixed user to attach to the ldap database,
258 #the password is not provided with the SSOLdapAuthenicationImpl
259 xwiki.authentication.ldap.bind_DN=<domain>\\<user>
260 xwiki.authentication.ldap.bind_pass=<password>
261 #Microsoft AD configuration
262 xwiki.authentication.ldap.UID_attr=sAMAccountName
263 xwiki.authentication.ldap.fields_mapping=name=sAMAccountName,last_name=sn,first_name=givenName,fullname=displayName,mail=mail,ldap_dn=dn
264 xwiki.authentication.ldap.group_memberfields=member,uniqueMember
265 #LDAP group mapping
266 xwiki.authentication.ldap.group_mapping=XWiki.XWikiAdminGroup=CN=WIKI_Admin,............|\
267 XWiki.XWikiAllGroup=CN=WIKI_User,...........
268
269 {code}
270 The java code
271 {code}
272 package com.wiki.sso;
273
274
275 import org.apache.commons.logging.Log;
276 import org.apache.commons.logging.LogFactory;
277
278 import com.xpn.xwiki.XWikiContext;
279 import com.xpn.xwiki.XWikiException;
280 import com.xpn.xwiki.user.api.XWikiUser;
281 import com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl;
282
283 import java.security.Principal;
284
285 public class SSOLdapAuthenicationImpl extends XWikiLDAPAuthServiceImpl {
286 /**
287 * Logging tool.
288 */
289 private static final Log LOG = LogFactory.getLog(SSOLdapAuthenicationImpl.class);
290
291
292 public XWikiUser checkAuth(XWikiContext context) throws XWikiException {
293 String user = getRemoteUser(context);
294 if ((user != null) || !user.equals("")) {
295 if (LOG.isInfoEnabled())
296 LOG.info("Launching create user for " + user);
297 if ( authenticate(user, context) != null ) {
298 if (LOG.isInfoEnabled())
299 LOG.info("Create user done for " + user);
300 user = "XWiki." + user;
301 context.setUser(user);
302 System.out.println("User is set to:" + user);
303 return new XWikiUser(user);
304 } else {
305 LOG.error( "User " + user + " can't be authenticated against ldap" );
306 }
307 }
308 return super.checkAuth(context);
309 }
310
311 /**
312 * We cannot authenticate locally since we need to trust the app server for
313 * authentication
314 *
315 * @param username
316 * @param password
317 * @param context
318 * @return
319 * @throws XWikiException
320 */
321 public XWikiUser checkAuth(String username, String password,
322 String rememberme, XWikiContext context) throws XWikiException {
323 String user = getRemoteUser(context);
324 if ((user == null) || user.equals("")) {
325 return super.checkAuth(username, password, rememberme, context);
326 }
327 return checkAuth(context);
328 }
329
330 private String getRemoteUser(XWikiContext context) {
331 String userName = context.getRequest().getHttpServletRequest()
332 .getRemoteUser();
333 if (userName != null) {
334 // only take the front of the username@domain
335 String[] elements = userName.split("@", 2);
336 userName = elements[0];
337 }
338 return userName;
339 }
340
341 public Principal authenticate(String login, XWikiContext context) throws XWikiException
342 {
343 if (LOG.isTraceEnabled()) {
344 LOG.trace("Starting LDAP authentication");
345 }
346
347 /*
348 * TODO: Put the next 4 following "if" in common with XWikiAuthService to ensure coherence This method was
349 * returning null on failure so I preserved that behaviour, while adding the exact error messages to the context
350 * given as argument. However, the right way to do this would probably be to throw XWikiException-s.
351 */
352
353 if (login == null) {
354 // If we can't find the username field then we are probably on the login screen
355
356 if (LOG.isDebugEnabled()) {
357 LOG.debug("The provided user is null."
358 + " We don't try to authenticate, it probably means the user is in non logged mode.");
359 }
360
361 return null;
362 }
363
364 // Check for empty usernames
365 if (login.equals("")) {
366 context.put("message", "nousername");
367
368 if (LOG.isDebugEnabled()) {
369 LOG.debug("LDAP authentication failed: login empty");
370 }
371
372 return null;
373 }
374
375 // If we have the context then we are using direct mode
376 // then we should specify the database
377 // This is needed for virtual mode to work
378 Principal principal = null;
379
380 // Try authentication against ldap
381 principal = ldapAuthenticate(login, "", context);
382
383 if (LOG.isDebugEnabled()) {
384 if (principal != null) {
385 LOG.debug("LDAP authentication succeed with principal [" + principal.getName() + "]");
386 } else {
387 LOG.debug("LDAP authentication failed for user [" + login + "]");
388 }
389 }
390
391 return principal;
392 }
393 }
394 {code}

Get Connected