Friday, January 26, 2007

SOAP over HTTPS

There are various mechanisms for securing the web services. Today, I will write about the scenario when a client needs to call a web service over HTTPS, provided the service is available over HTTPS.

This is Transport Layer Security (TLS) that runs beneath HTTP. Another is Message Level Security, which has many options (XML encryption etc) which is more secured.

This scenario is very common, though, it is not the perfect way of securing a web service, but it is used when, for example, a client is calling an authentication web service, by passing in the user id and password. Now, you don't want the password to go in clear text on HTTP, rather you would want this particular service be called over HTTPS.

Let's see how to make this happen. In theory, it is same as calling a URL in java using HTTPS.

First, go the the web service URL in your browser, using HTTPS and store its public certificate on your PC, in a file. This is done when the browser prompts the security warning about the server, view certificate and select copy to file, to save it on your local.

Once you have the server certificate, you need to store it in a keystore. I am using IBM HTTP Server, so I will use IKeyMan utility. However, this can be done using any corresponding utility provided by your HTTP server.

In IKeyMan, create a new JKS key store, select 'Signer Certificates' and click Add/Edit to add the saved server certificate to this keystore.

So, now we have the keystore containing the server's public certificate.

If your client is a Standalone Web Service client (meaning a stanalone java application), all you have to do is specify the location of this keystore using a java property before calling the web service over HTTPS.

Something like this, for IBM JRE:

System.setProperty("javax.net.ssl.trustStore","C:\\wsclient\\myWSClientKeystore.jks");
MyWSServiceProxy proxy = new MyWSServiceProxy();
boolean authenticatede = proxy.authenticate("john.doe@blogger.com");

Make sure the web service end point is using HTTPS.

Now, if you are using a Managed Web Service client, meaning one which is deployed in a EAR file (WAR or EJB), then you better import the server certificate in the keystore used by your application server or specify a new keystore in the application server.

Depending upon which application server you are using, the configuration options may be different. For example, IBM WebSphere has couple of options for doing this. A simple one is this:

Go to the WebSphere Admin console (I am using v5.1). Go to Security -> SSL. Here you will see SSL Configuration Repertoires. You can add cert in one of the existing keystores listed here, or add a new repertoire. When you add new, you can use the keystore we created above for standalone client. Please make sure 'Client Authentication' is not checked, as we are not doing the client authentication with the server.
Now, go to Web module -> -> Web Services: Client Security Bindings in the applications area, for you application. Under HTTP SSL Configuration, click Edit and enable SSL.

So, in this scenario, we did no authentication. However, with transport level security, there is also an option to do the authentication. Meaning, only the trusted clients can invoke a web service and get results.

In short, this can be achieved by generating a keypair (public key and private key) for the client. The keystore will contain server's public key certificate and client's public and private key.
The server will have to import the public key certificate of the client into its keystore. In this case, when a client calls the web service over HTTPS, the server will check if the request is coming from a trusted client, by decrypting the data using client's public key and its private key, and if decryption is successfull, will return the results.