Web Service Client (JAX-WS) in Weblogic(10.3) with 2 way SSL cannot complete the handshake

cxf, handshake, jax-ws, ssl, weblogic

We have been looking for a soution to our problem for one week and after looking in a lot of similar posts and after reading all the available documentation we haven't got a solution.

I'm going to explain my current situation and I hope someone could help us to solve the problem.

We have developed a Web Service Client in JAX-WS, which comunicates with a server-side Web Service in another platform. The comunication is 2 way SSL and we have the CA of the server side, to trust him, and our private certificates to identify in the server side.

Our Web Service Client is deployed in a Weblogic 10.3 and when it is going to make a call to the server-side Web Service, we load dinamically the truststore and the keystore which is loaded with just one certificate, because each time we are going to use a different certificate so we cannot use only a static keystore.

The problem is when we are stablishing the connection, negotiating the handshake because Weblogic ignores the truststore and keystore we loaded before the call and only look for the trusted certificates and the private keys in the Weblogic's keystores…

If we put our trusted certificate in the truststore of Weblogic and start the comunication again. We begin the handshake, we trust the server side (because now Weblogic find the CA in its keystore), but when our Web Service Client has to send the certificate to be trusted by the server-side, the "Certificate Chain" is empty and we get a "BAD_CERTIFICATE".

We have tried with Apache CXF and JAX-WS and the problem is the same, setting the keystores using the System properties and the libraries… So we don't know why our Web Service Client is not capable to send the certificate. It seems Weblogic is not serving them because of some reason, maybe Weblogic configuration, but we don't know.

If someone knows what we can do, plase tell us.

Thanks in advance.

Best Solution

Your problem is the SSL configuration on your client and server side. SSL handshakes issues aren't related to your web services configuration: Web services goes over HTTP, and is the java HttpsURLConnection that handle this.

A 2-way SSL handshake requires:

Client side

  • The server certificate should be in the keystore, or you can turn of this validation as explained setting this before using your web service client:

Code:

// Create a trust manager that does not validate certificate chainsTrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {    public java.security.cert.X509Certificate[] getAcceptedIssuers() {        return null;    }    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {      }    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {      }} };// Install the all-trusting trust managertry {    SSLContext sc = SSLContext.getInstance("SSL");    sc.init(null, trustAllCerts, new java.security.SecureRandom());    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());} catch (Exception e) {}
  • The server certificate 'server name' must match with the URL you are using to access the web service endpoint (checkURLSpoofing) or turn off this validation setting this before using your service client

Code:

// Create all-trusting host name verifierHostnameVerifier allHostsValid = new HostnameVerifier() {    public boolean verify(String hostname, SSLSession session) {       return true;    }};// Install the all-trusting host verifierHttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
  • Configure the client-side to sent correctly its certificate. Set this before using your web service client

Code:

System.setProperty("javax.net.ssl.keyStore", "path/to/your/key");System.setProperty("javax.net.ssl.keyStorePassword", "your-keystore-password");System.setProperty("javax.net.ssl.keyStoreType", "JKS");System.setProperty("javax.net.ssl.trustStore", "path/to/your/trust/keystore");System.setProperty("javax.net.ssl.trustStorePassword", "your-truststore-password");System.setProperty("com.sun.net.ssl.dhKeyExchangeFix", "true");

Server side

  • Add the client certificate to the trust store used by your server

This should work, if you keep having issues, add the stacktrace (client and server) to see what is going on.