ITIM Custom Authentication

ITIM allows you to provide your own custom authentication module which can be very useful to meet corporate authentication standards – such as authenticating with an authoritative LDAP, database or perhaps & more likely, AD.

ITIM ships with an example for a custom AD authentication provider in ${ITIM_HOME}/extensions/examples/authentication/adauthentication which is a really good place to start.

This shipped example covers enough about how to create the module so there is no need to repeat that here, but there are a couple of things that are worth pointing out to make things go a little better.

First of all, make sure your authentication factory matches the interface definition exactly;

public class ADProviderFactory implements
 AuthenticationProviderFactory {

 public ADProviderFactory() { }

 public AuthenticationProvider getProvider(Hashtable env)
 throws ConfigurationException {
 return (AuthenticationProvider)new ADAuthenticationProvider(env);

I’ve added in the class cast to AuthenticationProvider from the example that’s shipped to ensure there is no chance that the caller thinks that we’re not meeting the interface – although it certainly does work without it.

Personally I found the example a useful base for the ADAuthenticationProvider and ADAuthenticationHelper classes, but feel free to add your own customisation in there as needed.  In particular in a large enterprise there can be issues for *nix based ITIM servers using the example’s way of determining the AD domain controller to connect to.   Windows based ITIM servers won’t have this problem (I’ll try to make that into another post).

In the design of your AuthenticationProvider class I’d suggest considering some of the following;

  • The AuthenticationProvider has to end up returning a SystemUser.  It should really check that the ITIM user that’s returned is active.  It wouldn’t be great to allow active AD users to login to their inactive ITIM admin accounts…..gulp!
  • There is no need to be exclusive about the authentication provider.  You can try AD, then maybe go off and try a database, and perhaps if none of that works trying the plain old ITIM login itself.  Also, consider adding properties to the file to control which providers are active.
  • If you don’t mind a slight performance loss, move the loadProperties() call in the example into the authenticate method.  That way all your properties are dynamic and you don’t have to restart ITIM to pick up flag changes.
  • Be sure to add sufficient logging so you can see your module functioning.  Don’t over do it because although ITIM admins logging in won’t cause problems, if you have a lot of JNDI or web services happening then you may make your logs too noisy.  Also make sure you don’t do the usual security give-away’s by telling an attacker that an account name is wrong, or just the password was wrong – authentication failures should just state that the authentication failed – nothing more.
  • Don’t expose unnecessary details about your user repositories in the logs either.  Generic names should suffice so you can monitor progress.


When it comes to deployment there are a couple of points to add in;

  • First of all, put your new module in the classes directory of each of your WebSphere application servers.  So that’s /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/classes/ for a default install.  This is actually covered in an ISIM interim fix bit of doco update, but I’ve repeated it because it’s a pain to dig out the IV zip file just for that line.
  • Now, if you’re using a cluster you will also need to copy the jar into /opt/IBM/WebSphere/AppServer/profiles/DMgr/classes/.  If you don’t do this then you may see “class not found” errors for your AuthenticationProvider class when you’re in the WAS console.  Actually – I found these only when I was trying to change the ISIMSecurityDomain properties.
  • Finally, you need to add your new jar to the ITIM_LIB shared library.  Now, this isn’t that obvious at first, but it would appear that there are multiple classloaders working in ISIM so what I found is that login/authentication works fine, web services work fine, but JNDI calls from TDI don’t.  The solution is to add the class to ITIM_LIB.  The error I had was;
  • com.myorg.adauthentication.ADProviderFactory incompatible with ( class java.lang.ClassCastException)

Now that’s a little unpleasant, and it directs you back to your AuthenticationProviderFactory.  This problem is actually a classloader problem.  Because the classloader that is the login page loads the class and then the classloader that is the JNDI event handler also loads the class, they consider the classes to be different and then throw this exception.  So, by putting the jar into the ITIM_LIB shared library, you’re allowing the parent classloader to load the class – then when the child classloaders load it they can resolve the class to the common type that the parent loaded and this exception is avoided.  Ok – that was the longest explanation for putting something into ITIM_LIB ever…..


Now – with that in hand, restart the application servers (and the DMgr) if you’re in a cluster) and you should be ok.  I would  expect that you could use a symlink to the jar to avoid having multiple copies of the jar (not tested so don’t shoot me).

That’s it – you should now have your custom authentication provider working and authenticating your various clients – user’s logging in, web services, JNDI, etc…





JNDI Feed quick reference

A quick list of the main points to remember when using the ibm.JNDI connector to ISIM;


Provider URL: http://yourhost:9080/enrole/dsml2_event_handler

JNDI Driver:

Create an IDI feed service in ISIM, switch on “use workflow” to make sure workflows are run(!), set the naming context to be “dc=<yourNamingContext>” – this is used by the TDI AL’s

Include only the objectclass that maps to the Entity you want to create.  If you pass multiple then ISIM will choose one of them & generally it won’t be the one you want(!).

Ensure the ITIM service “user id” and password match those provided in the “Connection” tab in TDI.


In the output map provide $dn which should be in the form “uid=<uid for identity>,dc=serrviceNamingContext”

Map whatever attributes you want, or (and provided you validate the attribute list first!), map all attributes so that the AL isn’t affected by schema changes.


Set a link criteria to be;

ret.filter="(uid=" + work.getString("uid") + ")";

Set the search base to be the naming context of the IDI service in ITIM i.e. dc=<yourNamingContext>).

In the output map, set $dn “Add” to true and “Mod” to false.  Also set objectclass the same way.

You have to provide attributes in the attribute map for modify.  You can provide the whole schema if required (drag & drop) – ITIM will only update attributes that aren’t null.  Again, this is useful to protect against schema changes breaking the JNDI feed.


Set a link criteria to be;

ret.filter="(uid=" + work.getString("uid") + ")";

Set the search base to be the naming context of the IDI service in ITIM i.e. dc=<yourNamingContext>).

The Input map can be blank – it’s a delete after all.

Ok – that was the brutally cut down version, but it should be enough….


Problems and solutions

“ Server returned HTTP response code: 401 “ means that the username/password used to access the ITIM service is incorrect. HTTP code 401 is “Unauthorized” after all.

Under the “Advanced” part of the connector, set the following;

  • Authentication Method: Simple
  • Login username: <Match the User ID field in the service definition form in ITIM>
  • Login password: <Match the Password field in the service definition form in ITIM>

“The following exception occured while validating field: _batchRequestTypeChoiceList of class:'”

  •  Again, this can be an authentication issue.  Check the username / password on the JNDI connector.
  • It can also be caused by the “Link criteria” being specified incorrectly.  The link criteria should be specified as a valid LDAP filter, including brackets.  A simple mistake would be to specify a link criteria of “uid=myUserName”, this should be “(uid=myUserName)” (without quotes of course.

TDI 6.1.1 – delete method

The class is a really useful class for those times when you need a little more in terms of file manipulation than the ‘system’ object UserFunctions provide.

However, using this in TDI will throw up a little gotcha that can occur when using the delete method.

For example;

var dirObj = new"c:\\temp\\mydir");

Will generate the following error; Encountered "delete" at line..

The answer is to de-reference the method;

var dirObj = new"c:\\temp\\mydir");



Although TDI 7.1 FP5 ships with a JSON parser, it would appear that the parser doesn’t actually work (even at FP6).  The example AL that is shipped doesn’t work either – they both generate the same error – it looks like the JSON parser doesn’t quite register properly within the AL;

15:30:32,468 ERROR - [WriteJSON] CTGDIS810E handleException - cannot handle exception , initialize 
java.lang.Exception: CTGDIS159E This Connector has no configured Parser. 

This may be resolved in 7.1.1, but in this environment that version isn’t available.

Of course there is a workaround in the form of JSON Simple.  Drop the JSON Simple json-simple-1.1.1.jar into the “<IDI install dir>\jars” folder & restart TDI to make it available.

JSON Encoding

This is a simple approach which encodes an object as a JSON string.  The encoding will accept quite complex structures too.  I have it quite happily accepting a java.util.LinkedList where each element is itself a HashMap.  The only trick is that the JS object need to have been initialised properly;

// Init the object
var theObject = org.json.simple.JSONValue.parse("{}");

// Populate the object = "Mr Object"; = "999 ObjectHelp";

// Get the JSON string
var jsonString = org.json.simple.JSONValue.toJSONString(theObject);

JSON decoding

To decode JSON – again use a FileSystem connector & the following code;

var jsonString = work.getString("jsonString");
if ((jsonString != "") && (jsonString != null)) {
    var jsonWrapper = org.json.simple.JSONValue.parse(jsonString);
    g_QueryResult = jsonWrapper[0];

Generating JSON obviously has many uses, but in this case I was generating data to be consumed by a couple of jquery plugins – DataTables and jqplot.  More on how to generate the correct structure for those plugins later.