8 Replies Latest reply on Dec 21, 2006 1:09 AM by shilpee_k

    LDAP Newbie - LdapLoginModule

    jwisetech

      I know, I know...I should just be able to read the docs to find this out...but...can someone explain to me how this all works?

      My login-config.xml is setup as follows:

      <application-policy name = "Employees">

      <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
      flag = "required">
      <module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
      <module-option name="java.naming.provider.url">ldap://localhost:389</module-option>
      <module-option name="java.naming.security.authentication">simple</module-option>
      <module-option name="principalDNPrefix">cn=</module-option>
      <module-option name="principalDNSuffix">,ou=Employees,o=test</module-option>
      <module-option name="rolesCtxDN">ou=test-Roles,o=test</module-option>
      <module-option name="uidAttributeID">member</module-option>
      <module-option name="matchOnUserDN">true</module-option>
      <module-option name="roleAttributeID">cn</module-option>
      <module-option name="roleAttributeIsDN">false</module-option>
      </login-module>

      </application-policy>


      I know that I need to map role names within the web.xml to protect resources; however...

      my very simple question is how do I implement all of this?

      I have a custom login page, but how do I pass the username/password to the LdapLoginModule to perform it's validatePassword() method, and how then do I perform the context search for the user's roles, etc.?

      Again, I read so many docs that my head is spinning...I know I could write my own custom login modules but why re-invent the wheel that JBoss has already supplied, right?

      My assumptions are that JBoss automatically handles the connection to the LDAP server via the login-config.xml entries...what client code is needed to use that connection and do the additional roles searches, etc...

      Scott, et. al....sorry for the long post...TIA for any info.

        • 1. Re: LDAP Newbie - LdapLoginModule
          rafael.nunes

          Did you have some success?
          I have in the same situation.

          Could someone help me?

          • 2. Re: LDAP Newbie - LdapLoginModule
            jaikiran

            Have a look at:

            http://wiki.jboss.org/wiki/Wiki.jsp?page=LdapLoginModule

            If thats not what you are looking for, please provide more details about your application and also what exactly you are having problems with

            • 3. Re: LDAP Newbie - LdapLoginModule
              shilpee_k

              Hi,
              have done configurations in JBOSS (version :jboss-4.0.3SP1) to use LdapLoginModule authentication mentioned below. I have set up test ldap server using OpenLDAP and added entries as mentioned below.Problem is even if i dont start the LDAP server it still authenticates for correct username & password but if i give wrong password it fives LoginException. So i am not able to find out against what it is trying to match username/password if my LDAP server is not running.

              Please let me know if i have missed out something in configurations ?? Also, the code used to authentication in step 3 is correct or not ?

              Is it required to add loginmodule entry in auth.conf file for JBOSS ?

              Regards,
              Shilpee

              "sample.ldif" file to add entries in LDAP DB (data is stored in dbb file in OpenLDAP server)


              dn: dc=sample,dc=com
              
              objectClass: top
              
              objectClass: dcObject
              
              objectClass: organization
              
              objectClass: domainRelatedObject
              
              objectClass: dcObject
              
              associatedDomain: sample.com
              
              o: sample
              
              dc: sample
              
              description: Sample International - Specialist Providers of Widgets
              
              postalAddress: empty
              
              telephoneNumber: +44 00000000
              
              dn: cn=Directory Manager,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: organizationalRole
              
              objectClass: OpenLDAPdisplayableObject
              
              objectClass: labeledURIObject
              
              cn: Directory Manager
              
              cn: Manager
              
              cn: Directory Administrator
              
              cn: Administrator
              
              displayName: Directory Manager
              
              roleOccupant: uid=lrussell,ou=People,dc=sample,dc=com
              
              labeledURI: mailto:directorymanager@sample.com Directory Manager
              
              seeAlso: dc=sample,dc=com
              
              description: Manages the OpenLDAP directories
              
              dn: ou=People,dc=sample,dc=com
              
              ou: People
              
              objectClass: top
              
              objectClass: organizationalUnit
              
              dn: ou=Groups,dc=sample,dc=com
              
              ou: Groups
              
              objectClass: top
              
              objectClass: organizationalUnit
              
              dn: ou=Roles,dc=sample,dc=com
              
              ou: Roles
              
              objectClass: top
              
              objectClass: organizationalUnit
              
              dn: uid=lrussell,ou=People,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: person
              
              objectClass: organizationalPerson
              
              objectClass: inetOrgPerson
              
              sn: Russell
              
              cn: Luc
              
              uid: lrussell
              
              userpassword: fgCPCzLOHJSRIhLb756rLfe8E7Y=
              
              mail: lrussell@sample.com
              
              dn: uid=jbloggs,ou=People,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: person
              
              objectClass: organizationalPerson
              
              objectClass: inetOrgPerson
              
              sn: Bloggs
              
              cn: Joe
              
              uid: jbloggs
              
              userpassword: no3XJAZeeb9AKbGNY65/masWpZE=
              
              mail: jbloggs@sample.com
              
              dn: uid=fsmith,ou=People,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: person
              
              objectClass: organizationalPerson
              
              objectClass: inetOrgPerson
              
              sn: Smith
              
              cn: Fred
              
              uid: fsmith
              
              userpassword: kSgNNHCC/WXSjWH3s11BQNE6cKE=
              
              mail: fsmith@sample.com
              
              dn: cn=Users,ou=Groups,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: groupOfUniqueNames
              
              cn: Users
              
              uniqueMember: uid=jbloggs,ou=People,dc=sample,dc=com
              
              uniqueMember: uid=fsmith,ou=People,dc=sample,dc=com
              
              dn: cn=Member_admins,ou=Groups,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: groupOfUniqueNames
              
              cn: Member_admins
              
              uniqueMember: uid=lrussell,ou=People,dc=sample,dc=com
              
              dn: cn=Everyone,ou=Groups,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: groupOfUniqueNames
              
              cn: Everyone
              
              uniqueMember: uid=jbloggs,ou=People,dc=sample,dc=com
              
              uniqueMember: uid=fsmith,ou=People,dc=sample,dc=com
              
              uniqueMember: uid=lrussell,ou=People,dc=sample,dc=com
              
              dn: cn=Authenticated_users,ou=Roles,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: groupOfUniqueNames
              
              cn: Authenticated_users
              
              uniqueMember: cn=Everyone,ou=Groups,dc=sample,dc=com
              
              dn: cn=Member_admin,ou=Roles,dc=sample,dc=com
              
              objectClass: top
              
              objectClass: groupOfUniqueNames
              
              cn: Member_admin
              
              uniqueMember: cn=Member_admins,ou=Groups,dc=sample,dc=com
              
              


              "login-config.xml"

              <?xml version='1.0'?>
              <!DOCTYPE policy PUBLIC
               "-//JBoss//DTD JBOSS Security Config 3.0//EN"
               "http://www.jboss.org/j2ee/dtd/security_config.dtd ">
              
              <!-- The XML based JAAS login configuration read by the
              org.jboss.security.auth.login.XMLLoginConfig mbean. Add
              an application-policy element for each security domain.
              
              The outline of the application-policy is:
              <application-policy name="security-domain-name">
               <authentication>
               <login-module code="login.module1.class.name " flag="control_flag">
               <module-option name = "option1-name">option1-value</module-option>
               <module-option name = "option2-name">option2-value</module-option>
               ...
               </login-module>
              
               <login-module code="login.module2.class.name" flag="control_flag">
               ...
               </login-module>
               ...
               </authentication>
              </application-policy>
              
              -->
              
              <policy>
               <!-- Used by clients within the application server VM such as
               mbeans and servlets that access EJBs.
               -->
               <application-policy name="client-login">
               <authentication>
               <login-module code="org.jboss.security.ClientLoginModule" flag="required"/>
               </authentication>
               </application-policy>
              
               <!-- Security domain for JBossMQ -->
               <application-policy name = "jbossmq">
               <authentication>
               <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule"
               flag = "required">
               <module-option name = "unauthenticatedIdentity">guest</module-option>
               <module-option name = "dsJndiName">java:/DefaultDS</module-option>
               <module-option name = "principalsQuery">SELECT PASSWD FROM JMS_USERS WHERE USERID=?</module-option>
               <module-option name = "rolesQuery">SELECT ROLEID, 'Roles' FROM JMS_ROLES WHERE USERID=?</module-option>
               </login-module>
               </authentication>
               </application-policy>
              
               <!-- Security domain for JBossMQ when using file-state-service.xml
               <application-policy name = "jbossmq">
               <authentication>
               <login-module code = "org.jboss.mq.sm.file.DynamicLoginModule "
               flag = "required">
               <module-option name = "unauthenticatedIdentity">guest</module-option>
               <module-option name = "sm.objectname ">jboss.mq:service=StateManager</module-option>
               </login-module>
               </authentication>
               </application-policy>
               -->
              
               <!-- Security domains for testing new jca framework -->
               <application-policy name = "HsqlDbRealm">
               <authentication>
               <login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule "
               flag = "required">
               <module-option name = "principal">sa</module-option>
               <module-option name = "userName">sa</module-option>
               <module-option name = "password"></module-option>
               <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option>
               </login-module>
               </authentication>
               </application-policy>
              
               <application-policy name = "JmsXARealm">
               <authentication>
               <login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule"
               flag = "required">
               <module-option name = "principal">guest</module-option>
               <module-option name = "userName">guest</module-option>
               <module-option name = "password">guest</module-option>
               <module-option name = "managedConnectionFactoryName">jboss.jca:service=TxCM,name=JmsXA</module-option>
               </login-module>
               </authentication>
               </application-policy>
              
               <!-- A template configuration for the jmx-console web application. This
               defaults to the UsersRolesLoginModule the same as other and should be
               changed to a stronger authentication mechanism as required.
               -->
               <application-policy name = "jmx-console">
               <authentication>
               <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
               flag = "required">
               </login-module>
               </authentication>
               </application-policy>
              
               <application-policy name="sample_web_client_security">
               <authentication>
               <login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required">
               <module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
               <module-option name="java.naming.provider.url ">ldap://localhost:389</module-option>
               <module-option name="java.naming.security.authentication">simple</module-option>
               <module-option name=" java.naming.security.principal">cn=Directory Manager,dc=sample,dc=com</module-option>
               <module-option name="java.naming.security.credentials">secret</module-option>
               <module-option name="principalDNPrefix">uid=</module-option>
               <module-option name="principalDNSuffix">,ou=People,dc=sample,dc=com</module-option>
               <module-option name="uidAttributeID">uniqueMember</module-option>
               <module-option name="rolesCtxDN">cn=Directory Manager,dc=sample,dc=com</module-option>
               <module-option name="roleAttributeID">cn</module-option>
               <module-option name="matchOnUserDN">false</module-option>
               </login-module>
               </authentication>
               </application-policy>
              
               <!-- The default login configuration used by any security domain that
               does not have a application-policy entry with a matching name
               -->
               <application-policy name = "other">
               <!-- A simple server login module, which can be used when the number
               of users is relatively small. It uses two properties files:
               users.properties, which holds users (key) and their password (value).
               roles.properties, which holds users (key) and a comma-separated list of
               their roles (value).
               The unauthenticatedIdentity property defines the name of the principal
               that will be used when a null username and password are presented as is
               the case for an unuathenticated web client or MDB. If you want to
               allow such users to be authenticated add the property, e.g.,
               unauthenticatedIdentity="nobody"
               -->
               <authentication>
               <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule"
               flag = "required" />
               </authentication>
               </application-policy>
              
              </policy>
              


              web.xml:

              <web-app>
              
              <display-name>Compliance Engine</ display-name>
              
              <description>Web application Configuration of Compliance Engine </description>
              
              <servlet>
              
              <servlet-name>action</ servlet-name>
              
              <servlet-class>org.apache.struts.action.ActionServlet </servlet-class>
              
              <init-param>
              
              <param-name>config</ param-name>
              
              <param-value>/WEB-INF/struts-config.xml </param-value>
              
              </init-param>
              
              <init-param>
              
              <param-name>debug</ param-name>
              
              <param-value>6</ param-value>
              
              </init-param>
              
              <load-on-startup>2</ load-on-startup>
              
              </servlet>
              
              
              <servlet-mapping>
              
              <servlet-name>action</ servlet-name>
              
              <url-pattern>*.do</ url-pattern>
              
              </servlet-mapping>
              
              
              
              <security-constraint>
              
              <web-resource-collection>
              
              <web-resource-name>Sample Application </web-resource-name>
              
              <description>Require users to authenticate </description>
              
              <url-pattern>*.jsp</ url-pattern>
              
              <http-method>POST</ http-method>
              
              <http-method>GET</ http-method>
              
              </web-resource-collection>
              
              <auth-constraint>
              
              <description>Only allow Authenticated_users role </description>
              
              <role-name>Authenticated_users</ role-name>
              
              </auth-constraint>
              
              <user-data-constraint>
              
              <description>Encryption is not required for the application in general.
              
              </description>
              
              <transport-guarantee>NONE</ transport-guarantee>
              
              </user-data-constraint>
              
              </security-constraint>
              
              
              <session-config>
              
              <session-timeout>30</ session-timeout>
              
              </session-config>
              
              <distributable/>
              </web-app>
              


              Code used to perform supply authentication info.


              public synchronized UserVO authenticate(
               final String userId, final String password)
               throws Exception {
              
               UserVO userVO = null;
               try {
               MessageDigest d = java.security.MessageDigest.getInstance("SHA-1");
               d.reset();
               d.update(password.getBytes());
               BASE64Encoder encoder = new BASE64Encoder();
               String digestedPwdString = new String(encoder.encode(d.digest()));
               System.out.println("encoder -------- >> "+digestedPwdString);
               UsernamePasswordHandler handler =
               new UsernamePasswordHandler( userId.toLowerCase(),
               digestedPwdString.toCharArray());
               LoginContext loginContext =
               new LoginContext("sample_web_client_security", handler);
               loginContext.login ();
               /*
               * Login successful: - Get the subject - Get the principals list -
               * Add the current principal
               */
               Subject subject = loginContext.getSubject ();
               Set principals = subject.getPrincipals();
               SimplePrincipal user = new SimplePrincipal(userId.toLowerCase());
               principals.add(user);
              
               /*
               * Fetch the user from the database.
               */
               userVO = userDelegate.getUserByNetworkId(userId);
              
              
               }
               catch (final LoginException ex) {
               this.log.error(ex.getMessage(), ex);
               System.out.println(ex.getMessage());
               ex.printStackTrace();
               throw ex;
              
               } catch (final Exception ex) {
              
               System.out.println(ex.getMessage());
               ex.printStackTrace();
               throw ex;
               }
               return userVO;
               }
              
              


              • 4. Re: LDAP Newbie - LdapLoginModule
                jaikiran

                You will have to add a security-domain element in the jboss-web.xml. Have you done that?

                • 5. Re: LDAP Newbie - LdapLoginModule
                  shilpee_k

                  HI, Thanks for replying.
                  Yes i added in it in jboss-web.xml. Forgot to mention.

                  I am facing a new problem now. I am not able to access my login.jsp page. It gives COnfiguration error: can't authenticate against null principal.

                  In the code i posted, after successful login , the way i am adding user to principal , i m not sure its correct or not.

                  Please let me know how to add the principal.

                  • 6. Re: LDAP Newbie - LdapLoginModule
                    shilpee_k

                    Hi Jai,

                    Accessing JSP problem is solved . I am able to access the login.jsp.

                    I have one more doubt. In what all scenarios LoginException is thrown by LoginModule?

                    My objective is to allow a user to give only 3 login attempts and after 3 unsuccessful login attempts user's account should be locked. I have one flag in Database for failedLogin count in order to allow Admin to unlock user account.

                    So if LoginException is thrown only in case of Password mismatch then i am planning to implement it like this :
                    i can catch LoginException in catch block and update DB in catch block.

                    Please let me know how can i implement this failed login attempt functionality.

                    Also, is it correct to use UsernamePasswordHandler in LdapLoginModule in the code?

                    • 7. Re: LDAP Newbie - LdapLoginModule
                      jaikiran

                      LoginException is thrown when the authentication fails (one of them being invalid password). Yes, you can implement your use case of checking the number of attempts when LoginException is thrown. But remember that there might be various other reasons why the LoginException is thrown.

                      • 8. Re: LDAP Newbie - LdapLoginModule
                        shilpee_k

                        Yes. You are right.

                        So what is the other way to implement failed login attempt functionality? Please suggest.