Create a Java-based Liberator auth module

You can write your own Liberator auth module in Java using Liberator's Java Auth API.

If you want to integrate Liberator with your existing permissioning system, consider using Caplin's Permissioning Auth Module (PAM). The PAM subscribes to live permissioning data provided by one or more permissioning integration adapters, which you write using the Permissioning Integration API.

The PAM is packaged in the Permissioning Service blade, available as a separate download from Liberator. For more information about the Permissioning Service, see Permissioning.

Before you start

This example shows how to create a very simple Java-based service blade called 'PermissioningJavaBlade'. We'll use as a template the JavaOpenPermissioning blade that's included in the Deployment Framework.

You'll need a Liberator to help test your service blade while you develop it. If a Liberator isn't already deployed on a machine for this purpose, you'll need to deploy one to the Deployment Framework on your development machine. To do this, follow the instructions in How can I... Deploy Platform components to the Framework. You won't need to set up HTTPS connections or KeyMaster while you're developing the blade, so you can ignore the topics about those things.

Make sure that your Liberator licence allows access to Liberator's javaauth authentication module. The trial licence supplied with Liberator doesn't allow you to use javaauth. To see whether or not javaauth is licenced, deactivate the Liberator's built-in OpenPermissioning blade, activate its JavaOpenPermissioning blade, and then start the Liberator. If javaauth isn't licenced, Liberator reports "rttpd: Cannot load module javaauth - error not licenced".
Tip: In the following steps you'll be using the dfw command of the Deployment Framework. Before entering any dfw command as ./dfw <command-name>, make sure your current (working) directory is set to the Deployment Framework's topmost directory.

For a list of dfw commands, click here.

Blade structure

Assuming the blade is located in the Deployment Framework at <Framework-root>/kits/<blade_name>/<blade_name>/, relative to this path:

  • the blade compatibility information is in the file control 
  • the blade’s field definitions are in the file blade_config/fields.conf
  • Liberator related configuration for the blade is in the file Liberator/etc/rttpd.conf
  • The Liberator Java auth module's JAR file, compiled from the Java source file, is in Liberator/lib/java

Summary

In brief, you create the blade using the following steps, which are given in more detail further down the page:

  1. Create the blade's directory structure.
  2. Update Liberator's configuration.
  3. Update the blade control file.
  4. Deploy the blade to your development environment
  5. Write the Java auth module.
  6. Start the new Liberator permissioning blade.
  7. Package the new blade.

Create the blade's directory structure

  1. In a directory that's outside the Deployment Framework (say Temp_Java_blade), make a copy of the JavaOpenPermissioning blade's directory structure - the directory JavaOpenPermissioning within <Framework-root>/kits/ and everything within it.
  2. Rename the copy of the JavaOpenPermissioning directory in Temp_Java_blade to your new blade name: PermissioningJavaBlade

Update Liberator's configuration

A blade has to include configuration for the core Platform components that it interacts with.  In this case, the core component is just Liberator, which houses the Java auth module. Configuration for this module is located in the java.conf  and javaauth.conf files

  1. Edit java.conf
  2. Edit javaauth.conf
  3. Create the configuration override file
  4. Edit rttpd.conf
     

Edit java.conf

Using a suitable text editor, make the following changes to the file Temp_Java_blade/PermissioningJavaBlade/Liberator/etc/java.conf

  1. Change the file heading to 'Liberator Java configuration for PermissioningJavaBlade'
  2. Change the value of the add-javaclass > class-name configuration option to example.permissioning.SimplePermissioning
  3. Change the value of the add-javaclass > classpath configuration option to "${ccd}/../lib/java/SimplePermissioning.jar"

The configuration sample below shows the java.conf file with the changes highlighted:

#
# Liberator Java configuration for PermissioningJavaBlade 
# module 
#
#

#
# DO NOT EDIT THIS FILE !!!
#
#
# If you need to change any Java configuration, do so by updating
#
#    global_config/environment.conf
#    global_config/overrides/servers/Liberator/etc/java.conf
#
# Refer to the Deployment Framework documentation in the doc
# folder for more details.
#


jvm-location ${JVM_LOCATION}


# JARs required in the startup global classpath for the JVM
#
jvm-global-classpath    %r/lib/java/javaauth.jar

add-javaclass
    class-name   example.permissioning.SimplePermissioning
    class-id     authenticator
    classpath    "${ccd}/../lib/java/SimplePermissioning.jar"
end-javaclass

Edit javaauth.conf

Using a suitable text editor, make the following changes to the file Temp_Java_blade/PermissioningJavaBlade/Liberator/etc/javaauth.conf

  1. Change the file heading to "Liberator Java auth configuration for PermissioningJavaBlade."
  2. Change the value of the include-file configuration item to "
    ${BASE}/global_config/overrides/PermissioningJavaBlade/Liberator/etc/javaauth.conf"

The configuration sample below shows the javauth.conf file with the changes highlighted:

#
# Liberator Java auth configuration for PermissioningJavaBlade.
#
#

#
# DO NOT EDIT THIS FILE !!!
#
#
# If you need to change any Java authorisation configuration, do so by updating
#
#    global_config/environment.conf
#    global_config/overrides/servers/Liberator/etc/javaauth.conf
#
#
# Refer to the Deployment Framework documentation in the doc
# folder for more details.
#


###########################################################
#
#  Debug level - DEBUG,INFO,WARN,NOTIFY,ERROR,CRIT
#
###########################################################
log-level     INFO


###########################################################
#
#  Identifier for which class to load
#
###########################################################

javaauth-classid	authenticator

#
# Include override configuration..
#
include-file    "${BASE}/global_config/overrides/PermissioningJavaBlade/Liberator/etc/javaauth.conf"

Create the configuration override file

Liberator won't start if the override file specified in the include-file configuration item does not exist.

Create a file called <Framework-root>/global_config/overrides/PermissioningJavaBlade/Liberator/etc/javaauth.conf with the content below:

#
# Placeholder for overrides to the PermissioningJavaBlade's javaauth configuration.
#

Edit rttpd.conf

Using a suitable text editor, make the following changes to the file Temp_Java_blade/PermissioningJavaBlade/Liberator/etc/rttpd.conf

  1. Change the file heading to "Liberator configuration for PermissiongJavaBlade"

The configuration sample below shows the rttpd.conf file with the changes highlighted:

#
# Liberator congfiguration for PermissioningJavaBlade.
#
#

#
# DO NOT EDIT THIS FILE !!!
#
#
# If you need to change any configuration, do so by updating
#
#    global_config/environment.conf
#    global_config/overrides/servers/Liberator/etc/rttpd.conf
#
# Refer to the Deployment Framework documentation in the doc
# folder for more details.
#

include-dir "${ccd}"

auth-module    javaauth

Update the blade control file

Only one permissioning blade can be active at a time. Each Liberator service blade contains a blade control file, which lists the blades with which the blade is incompatible.

Using a text editor, make the following changes to the file Temp_Java_blade/PermissioningJavaBlade/control

  1. Add "JavaOpenPermissioning" to the list of conflicting blades

The configuration sample below shows the file Temp_Java_blade/PermissioningJavaBlade/control with the changes highlighted:

Conflicts: OpenPermissioning JavaOpenPermissioning PermissioningService CfgPermissioning TokenPermissioning XMLPermissioning

Deploy the blade to your development environment

Now you've created the initial configuration for the core components that use your Liberator permissioning blade, you can deploy this configuration in your development environment.

  1. ZIP the blade's directory hierarchy into a skeleton blade kit. The .zip archive must have a name of the form <blade_name>-<version_number>.zip. In the Temp_Java_blade directory, execute the following command from the command line:
    1. zip --recurse-paths PermissioningJavaBlade-000001.zip PermissioningJavaBlade
  2. Navigate to <Framework-root> and deactivate the existing built-in permissioning blades:
    1. ./dfw deactivate OpenPermissioning JavaOpenPermissioning
    2. Tip: You can first check the activation status of these blades by running ./dfw versions
  3. Navigate to <Framework-root> and deploy the skeleton blade kit:
    1. ./dfw deploy ../Temp_Java_blade/PermissioningJavaBlade-000001.zip

​​The ./dfw deploy command should respond with:

Boot-strapping the Deployment Framework

   Unpacking PermissioningJavaBlade kit PermissioningJavaBlade-000001.zip
   PermissioningJavaBlade-000001.zip successfully unpacked and stored in kits/archive

   Activating PermissioningJavaBlade

   Blades ok

And then ./dfw versions should show the new blade:

Deployment Framework           6.0.4-267113

   Core components                Version
   -----------------------------------------------------------
   Liberator                      6.1.0-275608
   Transformer                    6.1.0-275716

   Deployed blades                Version            State
   -----------------------------------------------------------
   PricingAdapter                 2013.09.27.1138    Active
   PermissioningJavaBlade                            Active

   Built-in blades                                   State
   -----------------------------------------------------------
   BlotterExport                                     Inactive
   DemoDataSource                                    Inactive
   DirectConnection                                  Active
   HTTP                                              Active
   HTTPS                                             Inactive
   JavaOpenPermissioning                             Inactive
   LiberatorJMX                                      Active
   LiberatorWebsite                                  Active
   MinimalLiberatorWebsite                           Inactive
   OpenPermissioning                                 Inactive
   ServerIdentification                              Active
   TransformerJMX                                    Active

Note: that deploying the skeleton PermissioningJavaBlade has automatically put it in the active state.

Write the Java auth module

This is the functional part of the blade that defines the actions you need it to perform. It is written using Liberator's Authentication Java API.  In this example, the Java source is in a single file called PermissioningJavaBlade.java. Create this file in a suitable place within your development environment. Ensure that the JAR containing the Liberator's Authentication Java API is in the compilation classpath. This JAR is called javaauth.jar and it's located in the lib/java/ directory of the deployed Liberator in the Deployment Framework.

The code example below is a modified version of the OpenAuthenticator.java example supplied with Liberator. Of course, if you wish, you can replace the example with a more sophisticated version of your own.

Important: Version 7 of Liberator's Authentication Java API added an extra parameter to the method signatures for Authenticator.checkRead and Authenticator.checkWrite. This is a breaking change. Check the API documentation for your version of the Liberator Authentication Java API for the correct method signature to use.

Here's the example code (for a Liberator 7 auth module):

package example.permissioning;

import java.util.Map;
import java.util.logging.Logger;

import com.caplin.server.auth.AuthenticationResult;
import com.caplin.server.auth.AuthenticationUser;
import com.caplin.server.auth.Authenticator;
import com.caplin.server.auth.DelayedResultReceiver;
import com.caplin.server.auth.MapObject;
import com.caplin.server.auth.PermissionUpdateType;
import com.caplin.server.auth.RTTPObject;
import com.caplin.server.auth.ServerNode;
import com.caplin.server.auth.SessionManager;
import com.caplin.server.auth.UserSession;
import com.caplin.server.logging.ServerLevel;

/**
 *
 * A simple Java Authenticator implementation that rejects attempts 
 * to log in to the Liberator.
 * It also logs debug information to the Liberator's auth-rttp.log 
 * logfile using the native logger.
 */
public class SimplePermissioning implements Authenticator
{
   private Logger logger;

   public void initialise( SessionManager sessionManager, 
                           DelayedResultReceiver delayedResultReceiver, 
                           ServerNode serverNode, 
                           String loggerName )
   {
      this.logger = Logger.getLogger(loggerName);

      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: initialise called: delayedResultReceiver={0}, serverNode={1}, loggerName={2}", 
                 new Object[] {delayedResultReceiver, serverNode, loggerName});
   }

   public AuthenticationResult checkUser( UserSession session )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: checkUser called: userSession={0}", 
                 new Object[] {session});
      return AuthenticationResult.INVALID_USER; // All user login attempts are invalid.
   }

   public AuthenticationResult releaseUser( UserSession session )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: releaseUser called: userSession={0}", 
                  new Object[] {session});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult newObject( RTTPObject object, RTTPObject parent )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: newObject called: object={0}, parent={1}", 
                 new Object[] {object, parent});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult releaseObject( RTTPObject object )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning releaseObject called: object={0}", 
                 new Object[] {object});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult checkRead( UserSession session, RTTPObject object, String requestedName )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: checkRead called: sessionId={0}, object={1}", 
                 new Object[] {session.getSessionId(), 
                 object});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult checkWrite( UserSession session, RTTPObject object, String requestedName,
                                           Map<String, String> fields )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: checkWrite called: sessionId={0}, object={1}, fieldMap={2}", 
                 new Object[] {session.getSessionId(), 
                 object, 
                 fields});
      return AuthenticationResult.DENY;
   }

   public AuthenticationResult mapObject( UserSession session, MapObject mapObject )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: mapObject called: sessionId={0}, mapObject={1}", 
                  new Object[] {session.getSessionId(), 
                  mapObject});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult requestObject( UserSession session, RTTPObject object )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: requestObject: sessionId={0}, object={1}", 
                 new Object[] {session.getSessionId(), 
                 object});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult discardObject( UserSession session, RTTPObject object )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: discardObject: sessionId={0}, object={1}", 
                 new Object[] {session.getSessionId(), 
                 object});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult authoriseHTTP( AuthenticationUser user )
   {
   logger.log(ServerLevel.DEBUG_LEVEL, 
              "SimplePermissioning: authoriseHTTP called: user={0}", 
              new Object[] {user});
   return AuthenticationResult.OK;
   }

   public AuthenticationResult checkUpdate( UserSession session, RTTPObject object, 
                                            String data )
  {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: checkUpdate called: sessionId={0}, object={1}, data={2}", 
                 new Object[] {session.getSessionId(), 
                 object, 
                 data});
      return AuthenticationResult.OK;
   }

   public AuthenticationResult checkPermissionUpdate( UserSession session, RTTPObject object, 
                                                      String key, Map<String, 
                                                      String> fieldValues )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: checkPermissionUpdate called: sessionId={0}, object={1}, key={2}, fieldValueMap={3}",
                 new Object[] {session.getSessionId(), 
                 object, 
                 key, 
                 fieldValues});
      return AuthenticationResult.OK;
   }

   public void globalPermissionUpdate( RTTPObject object, String key, 
                                       Map<String, String> fieldValues, 
                                       PermissionUpdateType type )
   {
      logger.log(ServerLevel.DEBUG_LEVEL, 
                 "SimplePermissioning: globalPermissionUpdate called: object={0}, key={1}, fieldValueMap={2}", 
                 new Object[] {object, key, fieldValues});
   }

   public void shutdown()
   {
      logger.log(ServerLevel.DEBUG_LEVEL, "SimplePermissioning: shutdown called");
      // do nothing
   }
}

If you look at the implementation of checkUser(UserSession) towards the top of the example, you'll see that this method always returns AuthenticationResult.INVALID_USER, rather than AuthenticationResult.OK. This isn't very useful behaviour for a real authentication module, but the main aim of this example is to show how to create a permissioning blade whose authentication module will load and run, rather than go into the details of how to code a fully functioned module. You'll see below that the simple behaviour of the module makes it easy to check whether the module is running by looking at the log files.

If you want to check out the behaviour of the module as implemented by its other methods, just change the return value of checkUser(UserSession) to AuthenticationResult.OK so that it will let you log on to the Liberator.

Package the Java class

When you've completed the code in the PermissioningJavaBlade.java file, package it as a JAR archive (PermissioningJavaBlade.jar), and put the archive in the directory <Framework-root>/kits/PermissioningJavaBlade/Liberator/lib/java/

Start the new Liberator permissioning blade

  1. Run the following command from the root of the Deployment Framework to restart Liberator:
    1. ./dfw start Liberator
  2. Clear your web browser's cache and record of logins, or close all browser windows and open a new browser window.
  3. Open the Liberator's status page and attempt to login with username 'admin' and the password 'admin'. Your credentials will be rejected.
  4. Look at the Java log file (java.log) in <Framework-root>/servers/Liberator/var. It should contain an entry that confirms the authentication Java class has been created:

14:37:25.403 +0000: INFO: Successfully created class authenticator 
(example.permissioning.SimplePermissioning)
  1. Look at the Liberator's auth module log file (auth-rttpd.log) in <Framework-root>/servers/Liberator/var. It should contain an entry that confirms the log in attempt has been rejected:
2014/01/21-14:40:47.274 +0000: INFO: Thread [Thread-2/18]: javaauth : 
checkUser: sessionId=0lp75vR2TDnHw8L1QI8XwV, 
userName=admin, password=admin: Authentication result: Failure: Invalid User

Package the new blade

When you've developed and tested the new blade to your satisfaction, you'll need to package it up so it can be deployed on your production system. See How can I... Package a custom blade.


See also: