LDAP Integration
WebContainerAuthenticationViaLDAP is another document about integration of LDAP, Tomcat and JSPWiki. You may find something useful there. Take a look.
-- David Gao

One can integrate JSPWiki running on Tomcat with Microsoft Active Directory via LDAP so you don't need to manage accounts in yet another location. There are two things that you'll want to get from Active Directory; authentication (is a username/password correct), and authorization (do they belong to a proper group).

Tomcat supports container managed security through a number of different "Realm" implementations. A realm is a set of users, passwords, and roles. All of this is documented fairly well on the Tomcat Realm "How to" page http://tomcat.apache.org/tomcat-5.5-doc/realm-howto.html#JNDIRealm. The realm implementation to use is the JNDIRealm. The Java Naming and Directory Interface (JNDI) has LDAP integration out of the box.

Update the conf/server.xml file with your ldap connection info#

In order to specify the Realm to be used, you need to update the conf/server.xml file. Comment or remove any other realm definitions and replace it with the intended JNDIRealm. This can be set up in a few different ways, but the way it is done below is to specify -
  1. connectionURL="ldap://domainserver.mycompany.com:389" URL to the ldap host (an accessible domain server)
  2. connectionName="ldapauth@mycompany.com" a connection name (Windows domain user that can read the Active Directory. Best to create a utility account for this so a deleting a person's account does not disable LDAP lookups in the future.)
  3. connectionPassword="mypassword" a connection password and password which has read ability on the LDAP database (basic window domain user). This value "mypassword" should be replaced with your password. If you don't want to store your password in the clear, the realm how to page describes a way to store it encrypted.
  4. referrals="follow" This is required if you need to search from the domain root of Active Directory.
  5. userBase="OU=MyCompany Users,DC=Mycompany,DC=com base location to start searching for users in the LDAP (Active Directory) tree. If you need to search the whole domain, remove the OU=MyCompany Users, and see Notes below.
  6. userSearch="(sAMAccountName={0})" this is the user name attribute in the user record for Active Directory. This is what the user will use to log on. It is typically JUST the usename portion of an email address. NOTE: {0} is a token that is replaced with whatever the user typed into the username filed upon login. Currently this is the only token available, unlike for the roleSearch attribute described below.
  7. userSubtree="true" means that searches for a user will descend into other directories. See troubleshooting notes below for DNS issues.
  8. roleBase="OU=MyCompany Users,DC=MyCompany,DC=com base location to start searching for roles in the LDAP (Active Directory) tree. A role is just a group that you create and add a user to in the Active Directory
  9. roleName="name" attribute of the group that is used to specify the name, typically "cn". NOTE: The value of the name attribute for any roles you are going to use needs to be identical with what you later set in your web.xml file for the web applications that are going to use container authentication.
  10. roleSubtree="true" means that searches for a role will descend into other directories
  11. roleSearch="(member={0}) member is an attribute on the role (group) that lists of all of the members. NOTE: A user will only be found if they are listed directly as members. If a group they are in is listed here instead of the user name, they will not be found to be in this role. In other words, do NOT list any groups in here because the role search will not look into any groups that are listed. It just does an exact comparison. NOTE2: {0} is a token that is replaced with the fully qualified name of the user once bound to JNDI. For example: CN=User Name,OU=MyCompany Users,DC=Mycompany,DC=com. {1} is also valid in this parameter and will be replaced with the string that the user typed in the username field to log in to the application: e.g. "username". If you are talking to Active Directory, you will most likely want to use {0}.
      <Realm className="org.apache.catalina.realm.JNDIRealm" debug="99"
      		connectionURL="ldap://domainserver.mycompany.com:389"
      		connectionName="ldapauth@mycompany.com"
      		connectionPassword="mypassword"
      		referrals="follow"
      		userBase="OU=MyCompany Users,DC=MyCompany,DC=com"
      		userSearch="(sAMAccountName={0})"
      		userSubtree="true"
      		roleBase="OU=MyCompany Users,DC=MyCompany,DC=com"
      		roleName="name"
      		roleSubtree="true"
      		roleSearch="(member={0})"
      />

Update the web.xml file in your web application#

Go to the webapps/jspwiki/WEB-INF directory and open the web.xml file. Go down to the <security-constraint> elements. In the sample from our updated jspwiki web.xml file below, notice that the <role-name> elements are set to "AD Dev Portal Admin" and "AD Dev Portal". These are the two groups that users of the wiki and administrative users for the wiki are in. If a wiki user is not in the "AD Dev Portal" they will not be able to edit, rename, upload, etc. (see the pages and access listed in the security constraints). Note that the data constraints are commented out because we have this on the inside network and aren't using SSL.
   <security-constraint>
       <web-resource-collection>
           <web-resource-name>Administrative Area</web-resource-name>
           <url-pattern>/Delete.jsp</url-pattern>
       </web-resource-collection>
       <auth-constraint>
           <role-name>AD Dev Portal Admin</role-name>
       </auth-constraint>
           <!--
       <user-data-constraint>
           <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
           -->
   </security-constraint>
      
   <security-constraint>
       <web-resource-collection>
           <web-resource-name>Authenticated area</web-resource-name>
           <url-pattern>/Edit.jsp</url-pattern>
           <url-pattern>/Comment.jsp</url-pattern>
           <url-pattern>/Login.jsp</url-pattern>
           <url-pattern>/NewGroup.jsp</url-pattern>
           <url-pattern>/Rename.jsp</url-pattern>
           <url-pattern>/Upload.jsp</url-pattern>
           <http-method>DELETE</http-method>
           <http-method>GET</http-method>
           <http-method>HEAD</http-method>
           <http-method>POST</http-method>
           <http-method>PUT</http-method>
       </web-resource-collection>

       <web-resource-collection>
           <web-resource-name>Read-only Area</web-resource-name>
           <url-pattern>/attach</url-pattern>
           <http-method>DELETE</http-method>
           <http-method>POST</http-method>
           <http-method>PUT</http-method>
       </web-resource-collection>

       <auth-constraint>
           <role-name>AD Dev Portal Admin</role-name>
           <role-name>AD Dev Portal</role-name>
       </auth-constraint>

           <!--
       <user-data-constraint>
           <transport-guarantee>CONFIDENTIAL</transport-guarantee>
       </user-data-constraint>
           -->
   </security-constraint>

Kerberos configuration is not needed as the ldap module tests passwords by attempting an authentication against the ldap server directly.

Debugging#

Ok, you do all of the above and it doesn't work. Now what? Well, there are three important tools for debugging.
  1. An ldap browser (such as JXplorer to test basic access and see how the directory and users are set up
  2. Ability to turn tomcat debugging all of the way up and check the log files to see what is going on. Check out http://tomcat.apache.org/tomcat-5.5-doc/logging.html for more information on that.
  3. Use the sample tomcat application (jsp-examples/security/protected/ - e.g. http://devportal/jsp-examples/security/protected/) to debug a simple case. Remember that you need to update the web.xml file for jsp-examples and make sure the role-name values are set to your values in the LDAP server, otherwise tomcat will not find any users you try. When you try the sample, if you fail to authenticate, then check the tomcat log to see what went wrong.

Referrals#

Searching anything other than a specific OU can result in "referrals". This is the AD server kicking back an answer that requires the client to search again. A possible issue of the AD server's DNS name can create problems. If your AD server is named "dc1.company.com" and your connectionURL queries that server, AD will likely kick back a referral with a server name of just "company.com". If the tomcat server is not using AD supplied DNS resolution, it will probably have problems with the URL returned for referrals. There are a number of ways to address this:

  • Edit your /etc/resolv.conf (or similar) and have the server use AD-based DNS
  • Editing the Tomcat server's /etc/hosts file to point the "company.com" domain name to one or all of the AD servers.
  • If your local AD server is a Global Catalog, do queries against port 3268 and no referrals will happen.

javax.naming.PartialResultException#

If you get an exception in catalina.out like so:
javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'dc=company,dc=com'
It is probably due to a need to follow referral searches. Add the referrals="follow" to the JNDIRealm in server.xml.

If you get

javax.naming.PartialResultException [Root exception is javax.naming.CommunicationException: company.com:389 
[Root exception is java.net.UnknownHostException: company.com]]
This is most likely due to the above mentioned notes on AD returning a root domain name as it's DNS server name.


Would you please give some real world examples for the less technically inclined among us? I think I have the server.xml edits figured out except for the (sAMAccountName={0}) and roleSearch="(member={0}) - what should {0} be? Thanks!

--Abby, 12-Apr-2007

Please see above...I have added some notes on what {0} does for each of these properties. Basically just type them straight in like that, as they are tokens that will be expanded with user provided information.

-- Chris, 31-Jan-2008


Hi,

is there any possibility to User AD-Integration and to user this LDAP-Groups in the groupdatabase.xml?

I have to offer the possiblity for an intern costumer, to manage the Groups in the wiki and adding ther LDAP-Groups (i implemented an AXIS-Frontend for this) to Wiki-"pseudo"-Groups ... i dont want a second organisation of groups and right and so on ...

Any Ideas? ... Thanks!

And Please AnswerMe!

--MartinU, 30-May-2007

Any Ideas how to help me?!

Thanks!

-- MartinU, 12th June 2007


For the proxy account for the connection in #2:

"... connectionName="ldapauth@mycompany.com" a connection name (Windows domain user that can read the Active Directory. Best to create a utility account for this so a deleting a person's account does not disable LDAP lookups in the future.) ..."

On my XpPro laptop with Adam installed on it, how can I create a "Utility Account"? I am on a Windows workgroup with a machine name. So how would this go? For example: Workgroup = mywg Machine = sparky Laptop account = myuser

In this case, please let me know what needs to be in the config line: connectionName="??????????"

Thanks, David.

--David, 06-Jun-2007


Hi,

I am using LDAP to authenticate users logging into my intranet portal. I have configured only my server.xml for the "Realm" tag. Is there anything else that needs to be done? Do i have to configure something else or write a java class or write a JSP.

Please advise. When i start tomcat, i got the following error.

Jun 7, 2007 9:56:05 AM org.apache.catalina.startup.Catalina start SEVERE: Catalina.start: LifecycleException: Exception opening directory server connection: javax.naming.AuthenticationException: LDAP: error code 49 - 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece --[ldapboom, 07-Jun-2007

Hi ldapboom,

have you ever looked for this "Error"-Message? ... if not, than you maybe found this useful ... ldapforum

-- MartinU


We can't encrypt the password of the JNDI resource.

I've found this on the Tomcat's user mailing list :

There is no way built in to tomcat to obfuscate the password on a JNDI resource. It's been discussed here on the list and the general concensus is to secure the server.xml file from prying eyes using file permissions and general server configuration.

--AnonymousCoward, 12-Jul-2007


I am able to follow the above instructions to integrate against an LDAP server. The security is working (i.e. required authentication on resources specified in the web-resource-collocation section of the web.xml file).

My problem are the following:

  • I cannot register a new user when I am not logged in (i.e. after I click on the "Join wikiname Now!" link on the login page.
  • I cannot create a profile after I successfully login using my LDAP username and password.

Both scenarios display the same error message:

  • You cannot set your login name because you are not logged in yet. You should log in first, using the credentials supplied by your administrator.

I have tried to remove the "<url-pattern>/Login.jsp</url-pattern>" in the web-resource-collection section of the web.xml file. I am able to register a new user. However, I am not able to login with my LDAP username and password.

Here are my goals:

  1. integrate with LDAP server (allow users to login with their LDAP username and password)
  2. allow the user to modify their profile in JSPWiki to set their their wiki name attribute to be used in the ACL setting. This is because I don't want users to use their LDAP username in setting the group membership and ACL setting. Our environment wants the LDAP username to not be that public (encourage only the username knows their LDAP username).

I am using the JSPWiki 2.6.0 on Tomcat 5.5.

Does anyone know how to use LDAP integration along with user profile modification? Thanks.

--AnonymousCoward, 08-Feb-2008


I can pass the authentication, but still get a "HTTP Status 403 - Access to the requested resource has been denied " in tomcat, the console doesn't throw any exception. don't know why? any further configuration or debug can do?

--vickey, 05-十一月-2008 11:08


another problem, if users login after a long interval, CommunicationException thrown, stack trace looks like below:

javax.naming.CommunicationException: connection closed [Root exception is java.i
o.IOException: connection closed]; remaining name 'DC=test'
        at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1965)
        at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1810)
        at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1735)
        at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:368)
        at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:338)
        at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:321)
        at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:248)
        at org.apache.catalina.realm.JNDIRealm.getUserBySearch(JNDIRealm.java:1084)
        at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:992)
        at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:941)
        at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:810)
        at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:258)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:417)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:619)
Caused by: java.io.IOException: connection closed
        at com.sun.jndi.ldap.LdapClient.ensureOpen(LdapClient.java:1558)
        at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:504)
        at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1948)
        ... 20 more
user can see error message on the web page as below:

HTTP Status 408 - The time allowed for the login process has been exceeded. If you wish to continue you must either click back twice and re-click the link you requested or close and re-open your browser


type Status report

message The time allowed for the login process has been exceeded. If you wish to continue you must either click back twice and re-click the link you requested or close and re-open your browser

description The client did not produce a request within the time that the server was prepared to wait (The time allowed for the login process has been exceeded. If you wish to continue you must either click back twice and re-click the link you requested or close and re-open your browser).

Got any solution?

--vickey, 06-十一月-2008 03:55


What do you mean in section "Update the conf/server.xml file with your ldap connection info" point 9 by "The value of the name attribute for any roles you are going to use needs to be identical with what you later set in your web.xml file for the web applications that are going to use container authentication."?

It's rather confusing. Please enlighten me. Thanks, Adrien

--Adrien, 27-Sep-2011 18:01


A strange think happening with me. for testing Im using sample tomcat application (examples/jsp/security/protected/) and configured realm as described in this article. Now when i enter valid username and passwd in the login form. it nither take me to index.jsp nor to error.jsp. it keeps me on the same login page. in the logs i can see a message that is INFO: SessionListener: SessionCreated('sessionid'). When I enter wrong password it take me to error.jsp and there is no error log in the logs. I have set log level to FINE. Do Im getting authenticated in first senario ? if yes why index.jsp not appearing.

Pl help ... I spend whole night on this, Kashif

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-34) was last changed on 31-Oct-2011 08:38 by David Gao