Monday, February 16, 2004


Securing a Web Service - Client Certificate

I did some minor clean up on the previous security entries to make them consistent. Now we are ready to make our SSL client work with client certificates. So far we were only trusting the server but of course we want to have the server trust the client too.

So first, let's create a client certificate and put it in our client.keystore keystore file:

<JAVA_HOME>\jre\bin\keytool -genkey -alias oc4j-cl -dname "CN=Client, OU=STJPG O=Oracle L=Redwood Shores, S=CA, C=US" -keyalg RSA -keypass welcome -storepass welcome -keystore client.keystore

<Note-March 4>

I was trying this again and was unable to get this to work unless as noted in the previous SSL entry that I used a certificate installed into the default JDK keystore "cacerts". This I believe is a minor problem in my client stub code that I just haven't had time to resolve. For a working example, the second time around this creation command becomes:

<JAVA_HOME>\jre\bin\keytool -genkey -alias oc4j-cl -dname "CN=Client, OU=STJPG O=Oracle L=Redwood Shores, S=CA, C=US" -keyalg RSA -keypass welcome -storepass welcome -keystore cacerts

</Note-March 4>

Next, like before, we need to export this so we can import into the server's keystore:

<JAVA_HOME>\jre\bin\keytool -export -alias oc4j-cl -storepass changeit
-file client.cer -keystore client.keystore

<Note-March 4>

Like the above comment on using cacerts, this would now become:

<JAVA_HOME>\jre\bin\keytool -export -alias oc4j-cl -storepass changeit
-file client.cer -keystore cacerts

</Note-March 4>

Then, copy the file over to where the server key store is located:

copy <JAVA_HOME>\jre\lib\security\client.cer <OC4J_HOME>\j2ee

And finally, import this client certificate into the server keystore - by now this is probably seeming pretty straightforward:

<JAVA_HOME>\jre\bin\keytool -import -v -trustcacerts -alias oc4j-cl -file client.cer -keystore server.keystore -keypass welcome -storepass welcome

Here is a picture of these steps:

Lastly, we want OC4J to ask the client for its certificate so that we get this mutual authentication. This is a quick change. Currently we have this configuration line in our secure-web-site.xml file:

<ssl-config factory="com.evermind.ssl.JSSESSLServerSocketFactory" keystore="../../server.keystore" keystore-password="welcome">
<property name="keyStore.password.obfuscated" value="welcome" />
<property name="provider" value="com.sun.net.ssl.internal.ssl.Provider" />
</ssl-config>

which we need to add needs-client-auth attribute to the ssl-config element, bolded below:

<ssl-config factory="com.evermind.ssl.JSSESSLServerSocketFactory" keystore="../../server.keystore" keystore-password="welcome"
needs-client-auth="true">
<property name="keyStore.password.obfuscated" value="welcome" />
<property name="provider" value="com.sun.net.ssl.internal.ssl.Provider" />

</ssl-config>

we need to run our client again, hopefully this time with a mutually trusted certificate exchange.

To see that these certificates are being used, try running OC4J with the following option:

java -Djavax.net.debug=all -jar oc4j.jar

This will print out what is going under the covers with your SSL communication and the certificates that are being used.

So is this topic finally beaten into the ground? Well, not quite. We still haven't explored Oracle's Certificate Authority to get real certificates nor have we explored WS-Security. Phew ... this is a big topic and as I work my way through hopefully you are starting to get a sense of the kind of tooling that would be useful to have for this kind of activity.

A couple of Web articles that were instrumental in getting me this far along with the documentation I pointed out as I went along here and complement this rather OC4J centric exercise:

* Web Services over SSL by Pankaj Kumar who has since written a book J2EE Security for Servlets, EJBs and Web Services
* Secure Your Sockets with JSSE from OnJava by Jamie Jaworski



comment []
10:18:12 PM