8. Authentication with LDAP

In this chapter, We create a Java EE 7 JSF application where the credentials are stored in an LDAP server. For testing purposes, we use a Java compliant version that can be started within the same JVM. The only change which is needed to have a real LDAP server is the configuration of the LDAP URL.

8.1 Main scenario

The code for this example can be found in the gitbook/ex8 directory of this Git Repository.

8.1.1 Basic Octopus setup

Instead of repeating all the different steps to define the basic requirements of a Java EE 7 JSF application with the Octopus framework, I refer to them in chapter 1. Just repeat the step 1.1.1 to 1.1.7 (included) but use for example the directory name ex8.

Some of the files need a small change and will be explained in the next sections.

8.1.2 Use Latest version of Octopus

  • Update the version property of Octopus to use the latest version of octopus framework.

    0.9.7.2</octopus.version>

8.1.3 Add LDAP server dependency

  • Add the following dependency within the pom.xml file for the Java LDAP server.

    com.unboundid unboundid-ldapsdk 4.0.4

8.1.4 Update the web.xml files

  • Specify a welcome files

      <welcome-file>/index.xhtml</welcome-file>
    

    </welcome-file-list>

8.1.5 Update the main user page

  • Place the html body contents within a element.

  • Add the logout functionality

  • Add some output which is dependent on the role of the user.

      <sec:securedComponent role="foo" />
    

    </h:outputText>

      <sec:securedComponent role="bar" />
    

    </h:outputText>

Add for this securedComponent tags, the following namespace definition.

xmlns:sec="http://www.c4j.be/secure"

8.1.6 Update the method supplying the AuthenticationInfo

  • Update the method getAuthenticationInfo() from the class be.atbash.ee.security.octopus.book.ex8.ApplicationSecurityData class

    @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) {

      if (authenticationToken instanceof UsernamePasswordToken) {
          UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
    
          AuthenticationInfoBuilder authenticationInfoBuilder = new AuthenticationInfoBuilder();
          authenticationInfoBuilder.principalId(usernamePasswordToken.getUsername());
          authenticationInfoBuilder.externalPasswordCheck();
    
          return authenticationInfoBuilder.build();
      }
      return null;
    

    }

8.1.7 Configure the credentialsMatcher

  • Specify the LDAP CredentialMatcher by putting the following lines in the src/main/resources/shiro_extra.ini file

    [main] LDAPMatcher = be.c4j.ee.security.credentials.ldap.LDAPCredentialsMatcher credentialsMatcher.matcher = $LDAPMatcher

  • Configure the LDAP CredentialMatcher by defining the following content in the file src/main/resources/octopusConfig.properties

    ldap.url=ldap://localhost:33389/

8.1.8 Add LDAP data and setup.

  • Create the class be.atbash.ee.security.octopus.book.ex8.LdapSetup which will initialize the LDAP server after deployment of the WAR.

Copy the code from https://github.com/atbashEE/octopus-examples/blob/master/gitbook/ex8/src/main/java/be/atbash/ee/security/octopus/book/ex8/LdapSetup.java.

  • Create the file src/main/resources/test.ldif with the LDAP records containing the test data.

Copy the file from https://github.com/atbashEE/octopus-examples/blob/master/gitbook/ex8/src/main/resources/test.ldif.

8.1.9 Test the application by following this test descriptive

  • Deploy the application on a Java EE 7 compliant application server capable of running on Java 8.
  • Open the browser pointing to the following URL : http:///ex8/index.xhtml
  • Click on the secured page link
  • Use the username - password combination rudy - secret1 and click on the login commandButton.
  • Verify if the text foo and bar is placed after the logout button.
  • Click the logout button.
  • Use the username - password combination user - secret2 and click on the login commandButton.
  • Verify that only the text foo is placed after the logout button.

8.2 Explanation

See also the explanation given in the sections 1.2.1. through 1.2.7 for the general concepts.

8.2.1 Update octopus version

The LDAP matcher, see further on, is only available in version 0.9.7.2 and later of Octopus.

8.2.2 Welcome file in web.xml

The element needs to be defined within the web.xml file so that after a log out from the application, the index page is shown again.

An alternative could be to define the parameter logoutPage within the /octopusConfig.properties configuration file.

8.2.3 Main user page

To verify the correct retrieval of the groups from the LDAP server, 2 output text components are added to the screen.

They are protected by a role, one is foo and the other one bar. By default, a 1-to-1 mapping between group and role is active within Octopus.

Later during the tests, we see that based on the user who has logged in, the text which appears is different based on the groups/roles it has.

8.2.4 Adjust authenticationInfo creation

In the case where we use the LDAP server, we can't perform the password validation ourself (Octopus framework), since we are not able to retrieve the password from the server. This is in contrast with other schemes like the one we saw in chapter 6 for example where we retrieved the hashed password of the user and supplied it to the Octopus framework.

Therefore, we need a special indication in the authenticationInfoBuilder to indicate that the password checks need to be done by an external system and therefore we call this method.

authenticationInfoBuilder.externalPasswordCheck();

This will mark this request that only manually defined matchers will be considered to validate the credentials.

8.2.5 Define the special Credential matcher

Since we have indicated that we need an additional matcher (implementing the interface org.apache.shiro.authc.credential.CredentialsMatcher) we need to configure one, capable of validating the user credentials using the LDAP server.

This needs to be done within the shiro_extra.ini file (as this is managed by Shiro) but a matcher for LDAP is included within Octopus since v0.9.7.2. First, we need to specify an instance of the matcher, done in our example with the $matcher variable. The second line adds then (because Octopus allows for Multiple matchers in contrast to Shiro) this matcher to the system.

The Octopus defined LDAPCredentialMatcher has many configuration properties, have a look at the user manual for an explanation of them.

The only required one (with no sensible default value) is the location where the server can be contacted.

  ldap.url=ldap://localhost:33389/

8.2.6 Test data

Before we can test the application, we need to have some users on the LDAP server. This is supplied by the ldif file and is loaded by the LdapSetup class. This is an EJB which has a method that is called when the application is deployed on the server.

8.2.7 Testing the application

When clicking on the secured link on the index page, we are redirected to the login page as we access a protected page, as defined within the securedURLs.ini. This is the same behavior as with the other examples. When we now enter our credentials, the ApplicationSecurityData#getAuthenticationInfo indicates that the credential matching needs to be performed by the developer, the LDAPCredentialMatcher.

That matcher searches within the LDAP server for a user with the correct username. When the DN entry is found, it connects to the server with this DN and the password supplied by the user. This way the user can just enter the username and doesn't need to know the DN.

When the connection is successful (and thus password is correct) it retrieves the groups the user belongs to.

These groups are immediately used to define the AuthorizationInfo (and not when an authorization check needs to be performed for that user) and placed in the cache. This way, additional connections to the LDAP server are not required.

8.3 Where to go next

  • ???

results matching ""

    No results matching ""