Skip to main content
Kinetic Community

LDAP Authenticator

External Auththenticator that verifies the user account from LDAP

Details

Kinetic Survey/Request has a plugin architecture for Authentication that is most often used to enable Single Sign-On (SSO) for web applications.

However, in some instances, a specialized authentication mechanism is desired. This article will outline the steps required to create an Authentication Plugin which authenticates a User via LDAP, without requiring LDAP authentication be enabled on the AR System.

Example code is provided and demonstrates how to configure the Plugin with different options. The example will be configurable to:

1. Send a User to an Account Request page if the AR Server is not Guest Enabled.

2. Alternately, create a record in the User form.

Usage

In order to setup an Authentication plugin,  one must follow three steps:


1. Create or install a Java class which extends the com.kd.kineticSurvey.authentication.Authenticator class.

2. Configure the plugin via the Survey/Request Administration Console.

3. Configure your Survey/Request template to use External Authentication.

 

Creating a Java Authentication Class

An Authentication class must extend the com.kd.kineticSurvey.authentication.Authenticator class. Additionally, it must support, at minimum the following two methods:

public boolean void authorizeSession()

public void authenticate(String userName, String password, String authentication)

The authorizeSession()  method.

authorizeSession is called each time a Template makes a call to one of Kinetic's Servlets. This determines the validity of the session. In this method, the UserContext object is available for testing with the isAuthenticated() method.

    public boolean authorizeSession() throws Exception {
        UserContext localUserContext = getUserContext();
        boolean authorized = false;

        if (localUserContext.isAuthenticated()) {
            logger.debug(LOGGER_ID + "User is already authenticated: " + localUserContext.getUserName());
            authorized = true;
        } else {
            // Indicate the user is being redirected
            localUserContext.setInRedirect(true);
            getRequest().getSession().setAttribute("UserContext", localUserContext);
            // Redirect to the login page
            String redirectURL = getRequest().getContextPath() + getProperties().getProperty("LOGIN_URL");
            logger.debug(LOGGER_ID + "User is not authenticated. Redirecting to:" + redirectURL);
            doRedirect(redirectURL);
        }

        return authorized;
    }

If the User is not Authenticated, we retrieve the LOGIN_URL from the property file and call the doRedirect() method (this is provided by the parent class and does not need an implementation.

When the Login Page is called, it submits the login form to the KSAuthenticationServlet. This Servlet checks the Survey/Request template's Authentication Type and isntantiates an instance of the Authentication class. For Default and Template authentication, this servlet authenticates against the AR System. For External authentication, the servlet creates an instance of this custom Authenticator class.

The authenticate() method

authenticate() is called and passed the Username, Password and Authentication string from the Login Page. This is where most of the heavy lifting is done to determine what to do with the Authentication. Ultimately, the intializeUserSession() method is called which creates a session with the Username supplied.

In the below code, we first validate the User's credentials against LDAP by calling the ldapAuthenticate() method. If no valid credentials are submitted, we fail the login and return the user to the login page with the error message.

If the User exists in the ARS User Form, then we initialize the Session with that username.

If the User does not exist but the AR Server allows Guest Access, we initialize the session with that usename as a guest.

If the User does not exist and the AR Server does not allow Guest Access, we check if the plugin is configured to create a User record for us. We then create a User record and initialize the session with the new username.

If creating a User record is disabled but submitting an Account Request is enabled, we redirect the User to the configured Account Request template.

Finally, if no valid combination of rules exists, we set the error message and return the User to the Login Page.

    public void authenticate(String userName, String password, String authentication) throws Exception {
        // Get the configuration propery values that will be used
        String enableAccountRequest = getProperties().getProperty("ENABLE_ACCOUNT_REQ");
        String accountRequestName = getProperties().getProperty("ACCOUNT_REQ");
        String enableCreateUser = getProperties().getProperty("ENABLE_CREATE_USER");
        
        // Get the UserContext object
        UserContext localUserContext = getUserContext();

        // Validate the credentials against the LDAP server
        DirContext ldapUser = ldapAuthenticate(userName, getRequest().getParameter("Password"));
        
        // If the credentials were no good, fail right away
        if (ldapUser == null) {
            localUserContext.setInRedirect(false);
            localUserContext.setErrorMessage("Login Failed. Please try again.");
            localUserContext.setAuthenticated(false);
            getRequest().getSession().setAttribute("UserContext", localUserContext);
            return;
        }

        // Check if the User record exists in Remedy
        if (userExists(userName)) {
            logger.debug(LOGGER_ID + "User " + userName + " exists in Remedy");
            intializeUserSession(userName);
            return;
        }

        // User did not exist in Remedy, but the Remedy server allows guest access
        if (isGuestEnabled()) {
            logger.debug(LOGGER_ID + "Logging in " + userName + " as a guest user");
            intializeUserSession(userName);
            return;
        }
        // The user did not exist in Remedy, and the Remedy server does not allow guest access,
        // Create a User record for this user
        if (enableCreateUser != null && enableCreateUser.equalsIgnoreCase("Yes")
        {
            // Create the user record
            logger.debug(LOGGER_ID + "Creating new User record for " + userName);
            createUserRecord(userName, ldapUser);
            // Login as the user
            logger.debug(LOGGER_ID + "Logging in "+userName+" using the newly created User record");
            intializeUserSession(userName);
            return;
        }
            // If the Account Request is enabled
       if (enableAccountRequest != null && enableAccountRequest.equalsIgnoreCase("Yes"))
       {
           logger.debug(LOGGER_ID + "Account Request is enabled");
            if (accountRequestName != null && accountRequestName.trim().length() > 0)
            {
                String redirectURL = getRequest().getContextPath() + "/DisplayPage?name=" + accountRequestName;
                localUserContext.setOriginatingPage(redirectURL);
                localUserContext.setInRedirect(true);
                getRequest().getSession().setAttribute("UserContext", localUserContext);
                logger.debug(LOGGER_ID + "Redirecting to Account Request URL " + redirectURL);
                doRedirect(redirectURL);
                return;
           }
       } else {
            //We have no valid configuration rules for this user. Redirect them back to the Login page.
            localUserContext.setInRedirect(false);
            localUserContext.setErrorMessage("No valid authentication rules exist for this User. Please try again with different credentials or contact your Administrator.");
            localUserContext.setAuthenticated(false);
            getRequest().getSession().setAttribute("UserContext", localUserContext);
            return;    
    
       }
    }

The full source of the LDAPAuthenticator class is attached to this article and outlines the other significant methods used to authenticate against an LDAP server, determine is a User exists and that the AR Server allows Guest Access, and creates the User Form record.

Example

Install the Plugin by copying the LDAPAuth.jar file to your kineticInstallRoot/kinetic/WEB-INF/lib directory and the ldapauthconfig.properties file to kineticInstallRoot/kinetic/WEB-INF.

Configuration of this plugin is done via the Survey/Request Administration Console.

To configure:

1. Open the Survey/Request Admin Console (http://yourserver/kinetic/AdminConsole).

2. Click "Edit Properties"

3. In the Remedy Server Settings section, check the "API Impersonate User" checkbox if the property is present.

4. in the SSO Adapter Setting section, set the following values

  a. SSO Adapter Class:    com.kd.kineticSurvey.authentication.LDAPAuthenticator

  b. SSO Adapter Properties: directory_path_to_install\kinetic\WEB-INF\ldapauthconfig.properties.

The result should resemble this:

LDAP_Auth_Config_cap.jpg

Once your Plugin is configured, enabled LDAP Authentication by selecting "External" for your Survey/Request Template's Authentication Type.

The ldapauthconfig.properties File

The final step to the process is setting the options in the Properties file in order to enable/disable the Authentication features desired as well as configure the LDAP connection.

The attached .properties file looks like this:

#LDAP Server
LDAP_URL=ldap://yourldapserver:389

#the URL for login redirection
LOGIN_URL=/login.jsp

#The pattern to use for formatting the user name. Use $ to represent the user's login id.
#For example:
#domain\$
#uid=$,ou=system
AUTH_PATTERN=yourdomain\\$

#Enable Account Request form
ENABLE_ACCOUNT_REQ=Yes
#The Name of the Unauthenticated submission template to use if the User
#does not exist in the User Form
ACCOUNT_REQ=AccountReq

#Enable User Form create
ENABLE_CREATE_USER=Yes

If you are using this as a template for creating your own Authenticator, a few items of note when looking at the options here.

1. Backslashes (and some other special characters) need to be escaped using a second backslash character.

2. The AUTH_PATTERN is implemented using a simple replace. This should work for most cases, but in the event a dollar sign ("$") is a significant character in your authentication string, that can be changed in the source.

3. Access to the values in the Properties file is done by calling getProperties().getProperty("PROPERTY_NAME"). This will always return a String.