Some news:
I’ve completed my Authentication Module, I tested the authentication logic in itself, and it works as expected. When presented with a valid certificate, it returns the corresponding user, when the certificate does not validate or is not mapped to any user, it returns null.
I’ve also deployed the package on the IS, complete with startup and shutdown services. The startup service creates a log file on the file system, I checked and the log file is there with some lines in it, showing that the Module is active.
I’ve also put the associated properties file in the config directory of the package, with all the data needed for the module to run.
And yet, when I try to connect to the IS through an HTTPS port which requires client certificates, it looks like the Module is never called.
The IS presents its certificate, I accept it, then Firefox asks me which certificate I want to authenticate with, I choose one, and if it’s a good one, I’m authenticated as usual, and if it’s not a valid one, I’m rejected as usual.
But when I look in the log file, there isn’t any line mentionning the failed attempt or the successful login, which makes me think that the Module never came into play, and all that took place was just the standard webMethods authentication process.
So now I’m wondering how to make my module override the standard IS authentication mechanism, or at least make my module the first mechanism to be used, falling back on the standard one, rather than the other way around.
The package has the following structure:
[PACKAGE_NAME] (package)
+[PACKAGE_NAME] (folder)
++AuthModuleFactory (folder)
+++AuthModuleFactory (empty java service)
++AuthModule (folder)
+++startup (java service)
+++shutdown (java service)
Here’s the code, may be there’s something wrong in it?
(I took away the names of some packages because they contained the name of the project, and it’s top secret!:p:)
The ModuleFactory: (this code is in the Source section under the Shared tab of the AuthModuleFactory folder)
protected Module instance;
public AuthModuleFactory(){
instance = new AuthModule();
}
public Module getInstance() {
return instance;
}
The Module:(this code is in the Source section under the Shared tab of the AuthModule folder)
/** Log stream, initialized during call to startup service */
public static LogOutputStream authlog = null;
/** set to TRUE to enable more logging */
public static boolean DEBUG = true;
/** CRL directory */
private static String crlDir;
/** Intermediate CAs directory */
private static String intermediateCADir;
/** Trusted certificates directory */
private static String trustedCertsDir;
/** maxPathLength parameter */
private static String maxPathLength;
/** Write a message to the module log
* @param s message to log
*/
public static void log(String s) {
if (authlog != null) {
authlog.write(s);
}
}
/** Write a message to the module log if DEBUG flag is true
* @param s message to log
*/
public static void debug(String s) {
if (DEBUG) log(s);
}
/** Check a X.509 certificate and map it to an Integration Server userid
* @return Integration Server userid.
*/
public String processToken(Token token) {
log("Authentication request");
if (token == null) return null;
String id = null;
try {
X509Token xt = (X509Token) token;
X509Certificate[] chain = xt.getCertificateChain();
X509Certificate clientCert = chain[0];
Session session = Service.getSession();
IDataFactory factory = new IDataFactory();
IData pipelineIn = factory.create();
IDataCursor cursorIn = pipelineIn.getCursor();
IDataUtil.put(cursorIn,"certificate",clientCert.getEncoded());
IDataUtil.put(cursorIn,"authoritiesDirectory",intermediateCADir);
IDataUtil.put(cursorIn,"trustSource",trustedCertsDir);
IDataUtil.put(cursorIn,"CRLsDirectory",crlDir);
IDataUtil.put(cursorIn,"maxPathLength",maxPathLength);
IData pipelineOut = Service.doInvoke(NSName.create("XXXXXXXXX.XXXXX:validateCertificate"),session,pipelineIn);
//this service is a standalone Java service which is used to validate a
//certificate against a list of CAs and trusted authorities, with CRL checking
cursorIn.destroy();
IDataCursor cursorOut = pipelineOut.getCursor();
cursorOut.first("validity");
boolean valid = IDataUtil.getBoolean(cursorOut);
String error = null;
if (cursorOut.next("error")) {
error = IDataUtil.getString(cursorOut);
if (error!=null){
log("ERROR:"+error);
}
}
cursorOut.destroy();
if (valid) {
IData pipelineIn_1 = factory.create();
IDataCursor cursorIn_1 = pipelineIn_1.getCursor();
IDataUtil.put(cursorIn_1,"issuer",clientCert.getIssuerDN().toString());
IDataUtil.put(cursorIn_1,"serialNum",clientCert.getSerialNumber().toString());
IData pipelineOut_1 = Service.doInvoke(NSName.create("wm.server.security.certificate:getDetailedInfo"),session,pipelineIn_1);
cursorIn_1.destroy();
IDataCursor cursorOut_1 = pipelineOut_1.getCursor();
cursorOut_1.first("user");
id = IDataUtil.getString(cursorOut_1);
cursorOut_1.destroy();
}
} catch (ClassCastException cce) {
log("class cast exception: " + cce); // Should never get this!
} catch (Exception e){
log(""+e);
}
if (id!=null){
log("User "+id+" successfully logged in");
}else{
log("Authentication failed");
}
return id;
}
The startup service:
// Setup a log file for the module
authlog = ServerAPI.getLogStream("AuthModule.log");
log("Authentication Module initializing");
// Load package configuration file.
File authconfig;
try {
authconfig = new File(Server.getResources().
getPackageConfigDir("XXXXXXXX"), "AuthModule.properties");
} catch (NullPointerException npe) {
throw new ServiceException("Could not get resources for Package XXXXXXX");
}
Properties authprop = new Properties();
try {
FileInputStream fis;
if (authconfig.exists()) {
fis = new FileInputStream(authconfig);
}else{
throw new ServiceException("Could not locate AuthModule config file");
}
authprop.load(fis);
fis.close();
}catch (IOException e){
throw new ServiceException("Could not load AuthModule.properties file: " + e);
}
String dbg = authprop.getProperty("debug", "false");
DEBUG = dbg.equals("true");
crlDir = authprop.getProperty("crlDirectory");
intermediateCADir = authprop.getProperty("intermediateCAcerts");
trustedCertsDir = authprop.getProperty("trustedAuthorities");
maxPathLength = authprop.getProperty("maxPathLength");
AuthenticationManager.registerMechanism(AuthModuleFactory.getMechanismName(),new AuthModuleFactory());
log("Authentication Module started");
The shutdown service:
log("Authentication Module shutting down");
AuthenticationManager.unregisterMechanism(AuthModuleFactory.getMechanismName());
log("Authentication Module disabled");