One and a half year after part 3, it is time to write another part in this series in which we discuss the establishment of single sign-on (SSO) from IBM Business Automation Workflow (BAW) (which was still known as IBM Business Process Manager (BPM) when I wrote the first three parts) with an Enterprise Content Management (ECM) system.
In part 1 (see Single sign-on with an external Enterprise Content Management system - Part 1: LTPA based), I discussed the reason to pass the credentials of the currently logged-in IBM BAW end user to the ECM system in favor of a functional identity. I also described the easiest way to set this up: by passing the IBM-proprietary Lightweight Third-Party Authentication (LTPA) token in a Web Services Security (WSS) header. While this is easy to setup, it has some limitations. Parts 2 (see Single sign-on with an external Enterprise Content Management system - Part 2: SAML based) and 3 (see Single sign-on with an external Enterprise Content Management system - Part 3: SAML based with customized SAML token content) therefore discussed how an alternative authentication token, the Security Assertion Markup Language (SAML) token, can be passed instead.
All these solutions have one common requirement: they require the ECM system to support tokens in the WSS header of the SOAP message. Not all ECM systems support this.
As you are also facing this with IBM’s CMIS 1.1 implementations for FileNet Content Manager and IBM Content Manager, and because the CMIS 1.0 implementation is deprecated (see this announcement: Software withdrawal and support discontinuance, search for CMIS on that page), it is time to solve this problem now.
So, let’s look at the solution:
Authentication to a web service endpoint can be performed in two ways:
- By using a WSS header with one of the many kinds of authentication tokens. This header is in the SOAP message = in the body of the HTTP request. From an HTTP perspective, the request is without any authentication information. This is called message level authentication and can also work with network intermediaries that do not support this particular authentication scheme.
- By using an HTTP header. This can be an Authentication header with a Basic authorization or Bearer token, but also any other token that is passed by a cookie. From an HTTP perspective, the request is authenticated. This is also referred to as transport-level authentication. If there are network intermediaries, pass-through of transport-level credentials is not always possible, therefore, this method is sometimes considered more suitable for point-to-point connections.
IBM’s CMIS 1.1 implementation only supports the HTTP header approach. As it can run on WebSphere Application Server (WAS), we are going to use an API that is described in the Using a WebSphere Application Server API to achieve downstream web single sign-on with an LtpaToken2 cookie topic. It retrieves the SSO token as a cookie name and value. This can then be passed to the target system. To inject the cookie into the outbound CMIS call to an ECM system, we are using a custom JAX-WS handler, a mechanism that was introduced in IBM BPM V8.5.6 – this is the minimum version that you need to use this solution.
A JAX-WS handler is a class that is injected into a Web Service invocation. It can modify HTTP request and SOAP message before it gets send out to the Web Service endpoint. It can also be used to modify the response before it gets passed to the real application.
We need to modify the request and do not touch the response.
// Check if we have an outbound message
The code first checks if the message is an outbound message. In this case, it retrieves the HTTP headers and the Cookie value. If they are not yet set, they are initialized. The SSO cookie is retrieved using the WebSecurityHelper.getSSOCookieFromSSOToken() API from WebSphere Application Server. This cookie is added to the cookies list and stored in the message context.
And that’s it.
The installation & configuration
Before you can install this handler on your IBM BAW environment, you need to ensure that the IBM BAW system as well as your ECM system use the same LTPA key. To establish LTPA based single sign-on between two WAS cells, a common LTPA key must be used. This can be reached by exporting the key from one cell and importing it into another cell as described in Import and export keys.
To install the JAX-WS handler, follow the steps outlined in the IBM BAW knowledge center: Registering custom JAX-WS handlers. You will need to copy the JAR file the APPSERVER_ROOT/lib/ext directory on all nodes of the application cluster and register the event handler in the cmisSsoJaxWsHandlers using wsadmin. To simplify the wsadmin part, I quickly implemented a script that you can run against your deployment manager: installHandler.pyView Details.
You can run it from the command line on the deployment manager profile:
DMGR_PROFILE_HOME\bin\wsadmin.bat -f installHandler.py -user ADMIN_USER -password ADMIN_PASSWORD
DMGR_PROFILE_HOME/bin/wsadmin.sh -f installHandler.py -user ADMIN_USER -password ADMIN_PASSWORD
With this handler registered, the outbound requests to the ECM servers will include an additional LTPA token cookie.
The default client policy set that by default sends a WSS header is still active. If you run this code, then the target ECM server likely responds with an exception stating that it cannot handle the request because of the WSS header with a mustUnderstand value 1.
You now have multiple options:
- You can change the client policy set and its binding to omit the WSS headers. This will work, but will also mean that any existing integration cannot anymore rely on this token.
- You can configure the client policy set to send the WSS header with a mustUnderstand=0. Then the target system can ignore this header.
I am going to explain option #2 here:
In the WAS admin console of your IBM BAW system, navigate to Services > Policy Sets > General client policy set binding > BPM SSO Client > WS-Security > Custom properties. Add an Outbound Custom Property com.ibm.wsspi.wssecurity.config.request.setMustUnderstand with a value 0. This setting is explained here: Web services security custom properties. Click OK and save your changes. In case of a clustered environment, synchronize all nodes.
Note: BPM SSO Client is the default client policy set binding that is set on the JAX-WS client for outbound CMIS calls when a new IBM BAW system is configured. A different one could be active on your system, for example when you followed the steps in the SAML-related posts in this series.
You need to restart the application cluster for the policy set binding and JAX-WS handler changes to become effective.
You learned how to register a JAX-WS handler for outbound CMIS web service calls from IBM BAW to an ECM system. You used this to inject an addition cookie into the HTTP request headers.
You can now configure your ECM server definition in the process application settings of IBM BAW to pass the user credentials to the ECM system, by disabling the Always use this connection information checkbox. Any interactions triggered by an end user will now run as the end user.
NOTE: There is one side effect that you should be aware of: you now send this LTPA token cookie to all ECM systems with Always use this connection information disabled. Even if an ECM system understands WSS, it might still try to work with this LTPA token and fail. Example: you configured SSO to a FileNet with the CMIS 1.0 endpoint that understands WSS. As token, you used SAML so that you do not need to exchange the LTPA token. If you now added the LTPA cookie to the requests to that system, then it will also try to parse this token and fail. To workaround that, you can further customize the code in the JAX-WS handler to only send the SSO cookie to well-known hosts.
To debug the solution, the following trace can help. It prints the web service requests and responses to the WAS trace.log and also shows the invocations of the event handler: com.ibm.ws.websvcs.trace.MessageTrace=all: com.ibm.ws.websvcs.trace.LogFilterInputStream=all: com.ibm.de.schwarzs.bpm.integration.ecm.LtpaCookieJAXWSHandler=all.
Other articles in this series:
- Single sign-on with an external Enterprise Content Management system - Part 1: LTPA based
- Single sign-on with an external Enterprise Content Management system - Part 2: SAML based
- Single sign-on with an external Enterprise Content Management system - Part 3: SAML based with customized SAML token content