About a year ago I started working on setting up a new interface for a customer. The interface was with a pretty well-known company with a reputation for data integrity in its API. As we got started, we learned that this integration was going to require OAuth 2.0 for Authentication as well as the use of SSL with security certificates. In addition, this interface also required Mutual SSL. With Mutual SSL both the client and the server must exchange signed certificates and verify each other’s trust chains before communication can begin.
If you are unfamiliar with the whole process, I will give you some lessons learned, and some insights into Mutual SSL and (more importantly) using Mutual SSL with IFS Connect. Mutual SSL is a hardened trust pattern for added levels of security.
Establishing Trust
In order for you to successfully communicate with mutual SSL you will need a few things first (even before even thinking about configuring IFS Connect. These include:
- OpenSSL tool for encrypting and generating certificates, keys, keystores, etc.
- A private key for cryptographic signing and encryption/decryption.
- A Certificate for IFS Connect - this certificate must be signed by a Certificate Authority for the remote server (not IFS or IFS Connect). This server may:
- already exist in the IFS Chain of Trust known as the TrustStore. On managed cloud you don’t have access to this directly and most of the time you would not need to either.
- Alternatively, you may need to add it to add the certificate, and possibly some intermediate certificates to IFS Connect as well.
- The Public Certificate for the remote server. Again, this certificate must be signed by a Certificate Authority or Intermediate Certificate that establishes the chain of trust.
- You can obtain this certificate by usually just navigating to a server endpoint using your browser and exporting the valid certificate.
- A Client ID & A Client Secret for REST using OAuth.
- There are several different alternatives to client ID * Client Secret, but these are the predominant options that work well with OAuth.
Words of Caution
Mutual SSL (while technically supported has its challenges. Since starting work on the project, I have struggled in one way or another with getting a full-fledged communication setup with IFS Connect. The main reasons being:
- A lack of clear detail in the documentation (I started working on 22R1 for this project) the documentation has improved since. (major improvements in fact)
- A variety of new IFS capabilities that worked in some cases but failed in others. When they work, they work great… when they don’t, we must turn to our friends in IFS Support and R&D.
- The discovery that no one that I could find (on community, in support, on the web, let alone coworkers had ever done Mutual SSL with IFS before)
So, as of today, we finally have active communication established (thanks to a work-around). Along the way, I have created multiple support cases (including one still pending), identified multiple issues that were addressed by R&D, and gone through multiple versions of IFS (22R1-23R2). While it took a while, I hope the work I did over the past 6-9 months will pave the way for secure communication with IFS Connect for everyone going forward.
Mutual SSL with IFS Connect
Mutual SSL in IFS Connect can be broken down into 4 main steps in establishing the Chain of Trust and for secure communication between IFS and a remote Server. If you have gathered all the items listed in the Establishing Trust section, then you are ready to do the following to set up IFS Connect:
- Create a KeyStore (PFX file) and store it (with a password) in the keystores page in IFS. Your keystore should be created using OpenSSL or equivalent and should include:
- The IFS Certificate
- All certificates are necessary to establish a Chain of Trust between your certificate and the CA from the remote server.
- The private key
- Create a Rest Sender Routing Address that:
- Points to the Remote Server endpoint
- You will need to use a method of Authentication (most likely OAuth Client Credential Flow)
- You will need to obtain from the remote server its public certificate and upload it onto the Routing Address (there is an upload certificate button). Be sure to not just have the certificate from the server, but any intermediate certificates, and root certificates as well and combine them into a single PEM file.
- Also, you will need to add special headers to indicate the name and encryption of your KeyStore
- Setup a Routing Rule to direct outbound messages to the endpoint.
OUTBOUND REST WITH MUTUAL SSL (STEP 1)
The Client will make a request of the server. For this step, you will need to have the server’s valid certificate loaded into your routing address. Not only must you have uploaded the entire Chain of Trust for the remote server’s certificate; but the chain must also be able to establish trust with at least one certificate in the IFS TrustStore. This could be a challenge because, in IFS managed Cloud, you will not have direct access to this. If you try to communicate with the server and the Chain of Trust cannot be established with the server then you will likely get an error of this trye:
ifs.fnd.connect.senders.ConnectSender$TemporaryFailureException: Exception while sending data Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed:
OUTBOUND REST WITH MUTUAL SSL (STEP 2)
With a trustable connection to the Server, you will be able to make your initial request of the server (this isn’t the OAuth or REST request but the request for Mutual SSL). The server will then try to send back its certificate to IFS Connect. Once received, IFS Connect will attempt to validate the certificate against the IFS Keystore identified in the routing address.
For this to work, a KeyStore must be set up and safely stored using a password in the KeyStore Page. It should include the Client Signed Certificate, full trust chain, including CA Certificate and the private key.
Connect will do the heavy lifting to handle encryption and decryption as long as everything is in the KeyStore, and the rouging address has the KeyStore headers such as:
ssl:KeyStoreId=<keystore name>
ssl:KeyStoreType=PKCS12
If you get a “malformed message” or an “unable to read” error from the server then this is usually an issue with your KeyStore
(In 22R2 this didn’t work so well but was resolved by R&D)
OUTBOUND REST WITH MUTUAL SSL (STEP 3)
Assuming step1 and step 2 have been successfully achieved, IFS Connect will attempt to send the IFS certificate from the KeyStore to the remote server for verification. If the certificate is valid and verifiable by the remote server then you should not have an issue.
if the server fails to validate the certificate, then you may get any variety of responses from the server (invalid certificate, malformed, or invalid) but in this situation the error should indicate that it is a response from the remote server (not IFS Connect).
OUTBOUND REST WITH MUTUAL SSL (STEP 4)
Once the remote server validates your certificate (secure communication can begin. It is at this point that Mutual SSL has been established and OAuth mediated communication will start. This step is the final step in the communication… but, involves a few additional communications if using OAuth:
- OAuth Authentication
The routing address established what type of authentication (Client Credential/ROPC/Bearer) that will be used to provide Authentication and authorize access to the endpoint.
(This step has been a challenge for IFS connect in various versions. At first OAuth didn’t work at all with Mutual SSL often producing out of bounds Java errors). This has improved and as of today 23R1 SU 7 Basic & Bearer Authentication work without issue.
Client Credential and ROPC still have a bug that prevents the client_secret from being decrypted correctly. When this happened you will see an error that looks like this:
ifs.fnd.connect.senders.ConnectSender$TemporaryFailureException: Error while trying to get the Oauth access token Caused by: ifs.fnd.connect.http.HTTPClient$UnauthorizedAccessException: POST error #401: Unauthorized access
* Notice in this message that it is a POST and it says OAuth to indicate that it is the token request that is failing.
While IFS addresses this, a few of my coworkers came up with a very clever workaround.
Option 1: Create a single routing address for calling the token endpoint and chain this request and response to the primary request.
Option 2: My solution involves explicitly setting the client ID and secret in a PLSQL rest call authorization properties.
* In both instances you will want to store the clien_secret in some location (preferably secure) that can be used in a rest invocation. When using Bearer token I have no difficulty… Client Credential is still buggy however:
- Message Request and Receipts
If you get through these steps and don’t receive an error, then you should either expect your message to have been delivered successfully or you should expect the response to your request to shortly be available in Application Messages.
I would love to hear if anyone else has had experience with this or other exotic communication methods using IFS connect.