Using X.509 Certificates for Identity Propagation with Web Service Security in WebLogic Server
By james.bayer on Apr 29, 2008
This was originally posted on my dev2dev blog April 29th, 2008.
One of my customers is considering a web services interface for exchanging information with their clients. Security is a very important consideration in their design, so they are considering using best practices for authentication, integrity and confidentiality. In this post I'll explain some detail around my experiences setting up a simple prototype using Web Service Security hands-on.
Currently they plan on using HTTPS for the transport, but SSL may be terminated by SSL hardware accelerators before it reaches the application server, so transport level security is not enough in this instance, we'll also need some message level security. The newer WS-Security 1.1 specification is available in the latest releases of WebLogic Server, but WS-Security 1.0 has maximum interoperability with other web services stacks. So it you are not in control of web service stack's that your clients are using, it's best to use the older standard. SAML, Username, and X.509 Token Profiles can be used for authentication. In this instance since certificates are already required for SSL, it will be straightforward to also use them to authenticate identity. This is a similar use-case to a previous dev2dev article posted on securing web services in WLS 9.2, but in this case we are going to use the X.509 certificates for the identity propagation instead of Username Token. The formal name for this is the OASIS WS-Security X.509 Token Profile. The identity in the certificate will map to an LDAP user.
Note that WebLogic Server ships with examples that perform User-name Token authentication located at <BEA_HOME>\wlserver_10.0\samples\server\examples\src\examples\webservices\wss1.1
I was not able to find a X.509 Token Profile example, so I wrote it up here and hopefully you can benefit from my experiences by getting this running and understand the steps in under an hour.
Client Certificate Setup
First, set up a java key store and certificate identifying a user that we can map to an LDAP user. In this example I use only the CN attribute. This CN attribute will map to a user in WebLogic's embedded LDAP, but you can use another enterprise LDAP (Active Directory, eDirectory, OpenLDAP) just as easily. We will use self-signed certificates in this simple example, but in production I would highly encourage you to use certificates issued by a Certificate Authority.
Now we need to export the pubic key to a .pem file so we can import it on the server side.
Some administrative configuration is required in the console to load the certificate into the trusted certificate chain and to tell the web services security stack to do identity propagation when X.509 tokens are found.
WebLogic ships with a DemoTrust keystore that can be used for testing purposes. Again, for production domains, you would want to not use the DemoTrust keystore, but it works well for prototyping the configuration steps. Here is how I imported the certificate into the keystore.
Web Service Security Configuration for the domain is also required. Follow the console configuration instructions here. Then follow the instructions here to configure the identity propagation with a Token Handler. Note that one of the steps will specify that we are using the CN attribute to map to the user name in LDAP.
If you have not already done so, create a user.
Server-side JWS Programming
In order to require authentication on a web service, you need only specify a policy via an annotation in the JWS file. WLS ships with a policy inside the weblogic.jar file known as Auth.xml (as well as Sign.xml and Encrypt.xml which are explained in the earlier article I mentioned). Here is a simple JWS file that shows how to attach that policy. This will require all users calling the time operation to be authenticated. Use the context object to retrieve the identity principal used to validate that we are indeed using an authenticated user.
Client-side JAX-RPC Programming
The normal way to generate JAX-RPC clients provided by BEA is to use clientgen. In this case we need to add a special parameter generatePolicyMethods="true" to indicate that policy is being used and generate extra methods on the stubs that are created. Here is the snippet from the build.xml file for ant that generates the client code.
The JAX-RPC client code specifies the policy that indicates which certificate to use for x509 identity propagation. It is different from just using the policy attached to the WSDL on the server-side because we need to give some guidance to the web service stack on the client as to how to embed the identity. Notice how we specify the CN=secuser in the TokenIssuer element. I have not included the policy element to sign the body to lower the overhead of the web service invocation. It is a trade-off of additional security versus performance.
Inside the Client.java file that makes use of the generated JAX-RPC classes from clientgen, simply specify the policy file in the constructor for the port.
There is also some special code required to set up reading from the keystore. I've commented out some code that illustrates how we would inject a Username token if we were using that approach instead.
When you run the client, you should see output like this if everything is working correctly.
If you encounter problems, then you can enable verbose debugging on both the client and server side by specifying the JVM argument -Dweblogic.wsee.verbose=* which will output to the standard out all the details over the web service requests and responses.
I have attached my Eclipse-based Workshop Studio projects from the WebLogic Portal 10.2 download to the site if you would like to try it out yourself. You may have to adjust some of the project settings to adjust the location of webservicesclient.jar and add the weblogic.jar to the ant classpath to generate the client. Hopefully my experiences with this simple prototype will benefit you.