Java™ Message Service (JMS) is a popular Java interface to message-oriented middleware products. In JMS, security is usually delegated to the messaging provider, with clients getting security configuration as part of the administered objects they use. However, the interface provides for user identification and authentication with the method:
public Connection ConnectionFactory.createConnection(String username, String password); |
This method is used to create connections to a queue manager (corresponding QueueConnectionFactory and
TopicConnectionFactory methods exist for domain-specific JMS applications).
By default, the authentication provided by these methods is rather limited in the WebSphere® MQ implementation of JMS. This article shows you how to use
new Object Authority Manager (OAM) functionality introduced in WebSphere MQ V6 to provide more comprehensive user authentication.
Using the OAM Authenticate User function
In order to provide customised username/password authentication, you need to to implement two new authorization service functions introduced in WebSphere MQ V6.
MQZ_AUTHENTICATE_USER is invoked by the queue manager to authenticate a user during connect calls,
while MQZ_FREE_USER is called to free resources when an application disconnects.
You also need to define an initialization entry point that calls MQZEP to register the implementations of
MQZ_AUTHENTICATE_USER and MQZ_FREE_USER.
All other authorization service entry points will be provided by the default OAM.
In this example, MQZ_AUTHENTICATE_USER will be implemented to only accept a user
testuser with password secret (in the example code they are defined as
constants USER_ID and PASSWORD).
Any other username/password combination will cause the function to return MQRC_NOT_AUTHORIZED,
which will cause a javax.jms.JMSSecurityException to be thrown on a JMS client.
An outline of the required code is shown below; for a full implementation, you can download the sample code.
Listing 1. A simple implementation of MQZ_AUTHENTICATE_USER
// hard-code a single allowed userId and password
const char USER_ID[] = "testuser";
const char PASSWORD[] = "secret";
/****************************************************************************/
/* Simple implementation of MQZ_AUTHENTICATE_USER. This retrieves a userId
/* and password from the supplied MQCSP structure, and compares them with
/* values defined above. If they match then it returns MQCC_OK and MQRC_NONE,
/* while if they differ it returns MQCC_FAILED with MQRC_NOT_AUTHORIZED.
/****************************************************************************/
static void MQENTRY EXAMPLE_AUTHENTICATE_USER(MQCHAR48 QMgrName, PMQCSP pSecurityParms,
PMQZAC pApplicationContext, PMQZIC pIdentityContext,
PMQPTR pCorrelationPtr, PMQBYTE pComponentData,
PMQLONG pContinuation, PMQLONG pCompCode, PMQLONG pReason) {
// if authType set to MQCSP_AUTH_USER_ID_AND_PWD then we need to check the userId and password
if (pSecurityParms -> AuthenticationType == MQCSP_AUTH_USER_ID_AND_PWD) {
// pointer to the UserId, and user Id length
MQPTR pUserId = pSecurityParms->CSPUserIdPtr;
MQLONG userIdLength = pSecurityParms->CSPUserIdLength;
// pointer to the Password, and password length
MQPTR pPassword = pSecurityParms->CSPPasswordPtr;
MQLONG passwordLength = pSecurityParms->CSPPasswordLength;
// do not continue with next service component
*pContinuation = MQZCI_STOP;
// check for null pointers to the userId and password
if (pUserId && pPassword) {
// check the username and password
if (strncmp((char*)pUserId, USER_ID, userIdLength) ||
strncmp((char*)pPassword, PASSWORD, passwordLength)) {
// strncmp returned a non-zero value, so they don't match
*pCompCode = MQCC_FAILED;
*pReason = MQRC_NOT_AUTHORIZED;
}
else {
// identical, return MQCC_OK
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
}
}
else {
// either pUserId or pPassword is null and can't be checked, so return MQCC_FAILED
*pCompCode = MQCC_FAILED;
*pReason = MQRC_NOT_AUTHORIZED;
}
}
else {
// authType is set to MQCSP_AUTH_NONE so no checking to do, return MQCC_OK and MQRC_NONE
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
}
}
|
The username and password are stored in a MQCSP structure, and a pointer to this structure,
pSecurityParms, is passed into the function when it is called. The function first checks to see if any authentication is required,
by seeing if the AuthenticationType attribute of the MQCSP structure is set to
MQCSP_AUTH_USER_ID_AND_PWD. If it is, the username and password are checked against hard-coded values using the
strncmp() function. If they both match, then the function returns MQCC_OK; otherwise it returns
MQCC_FAILED with reason code MQRC_NOT_AUTHORIZED.
The corresponding implementation of MQZ_FREE_USER is very simple; no resources were allocated by
MQZ_AUTHENTICATE_USER so it can just return MQCC_OK.
If resources were allocated by the authenticate user function, they should be freed here:
Listing 2. A simple implementation of MQZ_FREE_USER
static void MQENTRY EXAMPLE_FREE_USER(MQCHAR48 QMgrName, PMQZFP pFreeParms,
PMQBYTE pComponentData, PMQLONG pContinuation, PMQLONG pCompCode, PMQLONG pReason) {
// finally, simply return MQCC_OK
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
}
|
Finally, it is necessary to implement an entry point to invoke the MQZEP function to add the
EXAMPLE_AUTHENTICATE_USER and EXAMPLE_FREE_USER
functions to the entry point vector for this service component:
Listing 3. An entry point to register EXAMPLE_AUTHENTICATE_USER and EXAMPLE_FREE_USER
void MQENTRY MQStart(MQHCONFIG hc, MQLONG Options, MQCHAR48 QMgrName, MQLONG ComponentDataLength,
PMQBYTE pComponentData, PMQLONG pVersion, PMQLONG pCompCode, PMQLONG pReason) {
// return values
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
*pVersion = MQZAS_VERSION_5;
// Initialise the entry points that we have defined; EXAMPLE_AUTHENTICATE_USER first
MQZEP(hc,MQZID_AUTHENTICATE_USER,(PMQFUNC)EXAMPLE_AUTHENTICATE_USER,pCompCode,pReason);
// if that succeeded (i.e. pCompCode isn't MQCC_FAILED), initialize EXAMPLE_FREE_USER
if (*pCompCode == MQCC_OK) {
MQZEP(hc,MQZID_FREE_USER,(PMQFUNC)EXAMPLE_FREE_USER,pCompCode,pReason);
}
// if one of these failed, set the reason to MQRC_INITIALIZATION_FAILED
if (*pCompCode != MQCC_OK) {
*pReason = MQRC_INITIALIZATION_FAILED;
}
}
|
Here, two calls are made to MQZEP. The first registers the EXAMPLE_AUTHENTICATE_USER entry point,
and, if that succeeds, the second call registers EXAMPLE_FREE_USER.
If both calls succeed, the function returns MQCC_OK;
otherwise it returns MQCC_FAILED with MQRC_INITIALIZATION_FAILED.
Building the authorization service
The following sections show you how to build and install the authorization service on Microsoft® Windows® and on UNIX®. It is assumed that WebSphere MQ has been installed and configured to use its default directory locations. If different directories were specified during installation, then you need to modify the following commands as appropriate.
Microsoft Windows
On Windows, the authorization service must be compiled to a .dll and linked with mqm.lib
and mqmzf.lib. With Microsoft Visual Studio, use the procedure below. First, if necessary, set up the required paths:
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat |
Next, compile and link with the commands
cl /MD /W3 /Zp4 /D "WIN32" /D "_WINDOWS" /c /I "C:\IBM\WebSphere MQ\Tools\c\include" example.c link /subsystem:windows /dll "C:\Program Files\IBM\WebSphere MQ\Tools\lib\mqm.lib" "C:\Program Files\IBM\WebSphere MQ\Tools\lib\mqmzf.lib" example.obj /export:MQStart |
Finally, copy example.dll to the WebSphere MQ bin directory (usually
C:\Program Files\IBM\WebSphere MQ\bin.
UNIX platforms
On UNIX, you must link the authorization service with the shared libraries libmqm* and libmqmzf*
(threading suffixes and file extensions vary by platform). The OAM runs in a threaded environment, so you must use the threaded versions of these libraries.
The commands necessary to compile and link the authorization service vary depending on the platform.
The following commands show how to compile and link on 32-bit Linux and 64-bit AIX.
They will produce a shared library called example in the /var/mqm/exits directory:
Linux Intel (32-bit)
gcc -e MQStart -shared -I/opt/mqm/lib -L/usr/lib -lc -lnsl -ldl -lmqmzf_r -o /var/mqm/exits/example example.c |
AIX (64-bit)
xlc_r -q64 -e MQStart -bM:SRE -I/usr/mqm/inc -L/usr/mqm/lib64 -lmqmzf_r -o /var/mqm/exits/example example.c |
For information on compiling the authorization service on other platforms, see the WebSphere MQ Application Programming Guide.
Microsoft Windows
You must install the authorization service by editing the Windows registry (be careful when editing the registry).
Using the Windows regedit utility:
- Select the registry key
HKEY_LOCAL_MACHINE/SOFTWARE/IBM/MQSeries/CurrentVersion/Configuration/QueueManager/. - Open the appropriate
QueueManagerkey, for example,ExampleQM. - Select the
ServiceComponentkey.
The regedit window should now look like this:
Figure 1. Windows registry prior to adding the example authorization service

- Right-click
ServiceComponentand select New => Key. - Name the key
example.auth.service. - Left-click on the new key to select it.
- In the right-hand window, right-click and select New => String Value.
- Name the String Value
Name. - Right-click on the String value, select Modify, and enter the value
example.auth.service. - Repeat the last three steps to add three more String Values:
- name:
Module, value:C:\Program Files\IBM\WebSphere MQ\bin\example.dll - name:
Service, value:AuthorizationService - name:
ComponentDataSize, value:0
The regedit window should now look like this:
Figure 2. Windows registry after adding the example authorization service

Unix
On UNIX platforms, a stanza must be added to qm.ini. Edit the file
/var/mqm/qmgrs/QMname/qm.ini, where QMname is the name
of the WebSphere MQ queue manager being used, and add the following lines into the file before the default ServiceComponent stanza:
ServiceComponent:
Name=example.auth.service
Module=/var/mqm/exits/example
Service=AuthorizationService
ComponentDataSize=0
|
Install verification
The WebSphere MQ queue manager must be restarted before the new authorization service will be activated. After the queue manager has been restarted,
installation can be verified with WebSphere MQ Explorer. Start Explorer with the strmqcfg command, then right-click on the queue manager where the Authorization Service was installed, and select Properties. Next, select Installable Services
in the window that opens. The custom Authorization Service should be listed in the ServiceComponents tab:
Figure 3. Verifying installation with the MQ Explorer

WebSphere MQ JMS applications can connect to a WebSphere MQ queue manager in two ways. In bindings mode, clients connect directly to WebSphere MQ using the Java Native Interface (JNI), while in client mode they connect using Transmission Control Protocol/Internet Protocol (TCP/IP). The way in which the authentication service is used differs depending on which mode is selected.
Authentication in bindings mode
When bindings connections are used, the JMS username and password are passed directly to the OAM authenticate user function for authentication.
If the supplied credentials are rejected, then a javax.jms.SecurityException will be thrown.
With the example authorization service described above, the following code fragment:
Listing 4. Connecting to a queue manager with an invalid username and password
import javax.jms.*;
public class BindingsExample {
ConnectionFactory cf = null;
Connection conn = null;
public static void main(String[] args) {
try {
//configure JNDI context
Context ctx = new InitialDirConext(...);
// get a pre-defined connection factory from JNDI
cf = (ConnectionFactory)ctx.lookup("ExampleCF");
// connect
conn = cf.createConnection("myUser","myPassword");
}
catch (Exception e) {
//process JMSException/NamingException etc.
}
}
}
|
will result in the exception:
javax.jms.JMSSecurityException: MQJMS2013: invalid security authentication supplied for MQQueueManager |
If the createConnection(...) method call is replaced with
conn = cf.createConnection("testuser","secret"); |
then the Connection will be created successfully.
Authentication in client mode is slightly more complex. By default, the JMS client will not send an MQCSP structure to a queue manager when it connects in client mode. If the authorization service is to be used, this structure must be defined in a client security exit:
- When the exit is invoked with the exit reason
MQXR_SEC_PARMS, the exit creates a newMQConnectionSecurityParametersobject. - The exit gets the username and password supplied to the JMS
createConnection(String username, String password)method from the fieldschannelDefParms.remoteUserIdandchannelDefParms.remotePassword, wherechannelDefParmsis theMQChannelExitobject passed to the exit when it is invoked. - The exit modifies the userId and Password if required (for example, to hash the password for transmission; in this case the authorization service would also have to be
coded to use a hashed password) and sets them in the
MQConnectionSecurityParametersobject using the methodssetCSPUserId(String UserId)andsetCSPPassword(String password). - The exit sets the
authenticationTypefield toMQC.MQCSP_AUTH_USER_ID_AND_PWDusing the methodsetAuthenticationType(int authType). - Finally, the exit sets the
MQConnectionSecurityParametersobject into theMQChannelExitobject using the methodsetMQCSP(MQConnectionSecurityParameters csp):
Listing 5. A simple Security exit fragment that creates a MQConnectionSecurityParameters object
package example;
public class SecurityExit implements com.ibm.mq.MQSecurityExit {
public byte[] securityExit(MQChannelExit channelExitParms,
MQChannelDefinition channelDefParms,
byte[] agentBuffer) {
switch (channelExitParms.exitReason) {
case MQC.MQXR_INIT:
// initialize etc.
break;
case MQC.MQXR_INIT_SEC:
// transmit MCAUserId if desired etc.
break;
case MQC.MQXR_SEC_PARMS:
// create a new MQCSP object
MQConnectionSecurityParameters csp = new MQConnectionSecurityParameters();
// set authenticationType to AUTH_USER_ID_AND_PWD
csp.setAuthenticationType(MQC.MQCSP_AUTH_USER_ID_AND_PWD);
// set CSP UserId and password from the JMS-supplied values
csp.setCSPUserId(channelDefParms.remoteUserId.trim());
csp.setCSPPassword(channelDefParms.remotePassword.trim());
// finally add MQCSP object to the channelExitParms
channelExitParms.setMQCSP(csp);
break;
case MQC.MQXR_TERM:
// etc.
}
return agentBuffer;
}
}
|
If MQChannelExit.getMQCSP() is non-null when the exit returns after being invoked with
MQXR_SEC_PARMS, then the contents of the MQConnectionSecurityParameters object defined by the exit
will be transmitted to the queue manager and passed to the authorization service for authentication.
Two additional configuration steps are necessary. Firstly, the supplied CSPUserId must correspond to a user on the target server.
Secondly, it may be necessary to set the MCAUSER property on the channel being used to a user with authorization to access queue manager resources. In a full security solution, this would usually be set by the client security exit when invoked with MQXR_INIT_SEC,
but it may also be set with WebSphere MQ Explorer, or with the runmqsc command:
alter channel(channel name) chltype(svrconn) mcauser(UserId) |
If the ConnectionFactory is defined in a JNDI namespace, the exit can be set using the JMSAdmin tool with the command:
ALTER CF(CFname) SECEXIT("example.SecurityExit") |
The ConnectionFactory must be set to use TRANSPORT(CLIENT); otherwise this command will fail.
If the ConnectionFactory is defined programmatically, the exit can be set as follows:
ConnectionFactory cf = new MQConnectionFactory();
cf.setSecurityExit("example.SecurityExit");
|
Creating a Connection with this ConnectionFactory will now use the example authentication service to verify the supplied username and password.
This article has shown how to implement and deploy a custom authentication service, and how to use it from JMS applications. The example is simple, but includes all the elements necessary to provide customised authorization for connection requests from a WebSphere MQ JMS client.
The author would like to thank Eileen Dreyer for reading the manuscript, and David Postlethwaite for frequent advice about the workings of the Object Authority Manager.
| Description | Name | Size | Download method |
|---|---|---|---|
| Code sample in zip format | example.zip | 2 KB | FTP |
Information about download methods
- SSL configuration of the Websphere MQ Java/JMS client
This article shows you how to use SSL to secure a connection from a JMS client to a WebSphere MQ Queue Manager. - WebSphere MQ System Administration Guide
More information about authorization services and the MQZ_AUTHENTICATE_USER and MQZ_FREE_USER functions. - WebSphere MQ Application Programming Guide
More information about how to compile and link code for shared libraries. - WebSphere MQ product page
Product descriptions, product news, training information, support information, and more. - WebSphere MQ documentation library
WebSphere MQ manuals in PDF format. - WebSphere MQ V6 Information Center
A single Eclipse-based Web interface for all WebSphere MQ V6 documentation. - WebSphere Business Integration products
page
For both business and technical users, a handy overview of all WebSphere Business Integration products - developerWorks WebSphere Business Integration zone
For developers, access to WebSphere Business Integration how-to articles, downloads, tutorials, education, product info, and more. - Trial downloads for IBM software products
No-charge trial downloads for selected IBM® DB2®, Lotus®, Rational®, Tivoli®, and WebSphere® products. - Most popular WebSphere trial downloads
No-charge trial downloads for key WebSphere products. - Safari Bookshelf: e-library designed
for developers
Complete search and download access to thousands of technical books for a one-time subscription fee. Free trial for new subscribers. - WebSphere forums
Product-specific forums where you can ask questions and share your opinions with other WebSphere users. - developerWorks blogs
Ongoing, free-form columns by software experts, to which you can add your comments. Check out Grady Booch's blog on software architecture and engineering.
Ben Ritchie is a software engineer at the IBM Hursley Software Lab in the UK, and he works as a Java developer on the WebSphere MQ Client Development team. Ben joined IBM in 2001 after completing a DPhil in astrophysics at the University of Sussex, and has worked with JMS ever since, first with WebSphere MQ Everyplace and more recently with WebSphere MQ. You can contact Ben at ben.ritchie@uk.ibm.com.




