title: Spring WS Client — Authentication with Server and Client Certificates
body: <p>I need to be able to do a "client cert" authentication for a SOAP service.</p>
  
  <p>I'm using Spring WS. I have: a <code>my.key</code>, a <code>myCA.pem</code>, and a <code>myClient.crt</code>.</p>
  
  <p>This is my relevant Java piece of code (I know it's still messy but I'm just trying <em>to get it to work</em> first):</p>
  
  <pre><code>public TheResponse doIt(TheRequest request) {
    log.info("Sending request...");
    try {
      InputStream is = new FileInputStream(new File("src/main/resources/keystore.jks"));
      KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
      keyStore.load(is, "keystore!passwd".toCharArray());
      is.close();
      KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
      keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
  
      InputStream is1 = new FileInputStream(new File("src/main/resources/truststore.jks"));
      KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
      trustStore.load(is1, "truststore!passwd".toCharArray());
      is1.close();
      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
      trustManagerFactory.init(trustStore);
  
      HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
      messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
      messageSender.setTrustManagers(trustManagerFactory.getTrustManagers());
      setMessageSender(messageSender);
  
      return (TheResponse) getWebServiceTemplate().marshalSendAndReceive(request,
          new SoapActionCallback("https://domain/tld/icc/SomePathDownTheLine"));
    } catch (Throwable e) {
      log.error("Sh*t didn't work due to:", e);
      throw new GatewayConnectionException(String.format("Unexpected error while sending request [%s]", e.getMessage()));
    }
  }
  </code></pre>
  
  <p>This is how I'm building the trust- and key- stores:</p>
  
  <pre><code># KeyStore
  $ openssl pkcs12 -export -in myClient.crt -inkey my.key -out keystore.p12 -name my_key -CAfile myCA.pem -caname root
  
  $ keytool -importkeystore -deststorepass keystore!passwd -destkeypass keystore!passwd -destkeystore keystore.jks \
    -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass keystore!passwd -alias my_key
  
  # Trustore (using truststore!passwd)
  $ keytool -import -trustcacerts -alias my_ca -file myCA.pem -keystore truststore.jks
  
  $ keytool -import -trustcacerts -alias my_cc -file myClient.crt -keystore truststore.jks
  </code></pre>
  
  <p>...and these are the verification steps:</p>
  
  <pre><code>$ keytool -list -keystore keystore.jks -storepass ********
  
  Keystore type: JKS
  Keystore provider: SUN
  
  Your keystore contains 1 entry
  
  my_key, Oct 17, 2017, PrivateKeyEntry,
  Certificate fingerprint (SHA1): 1A:9D:6A:65:. . .:E6:C1:90
  
  $ keytool -list -keystore truststore.jks -storepass ********
  
  Keystore type: JKS
  Keystore provider: SUN
  
  Your keystore contains 2 entries
  
  my_cc, Oct 17, 2017, trustedCertEntry,
  Certificate fingerprint (SHA1): 1A:9D:6A:65:. . .:E6:C1:90
  my_ca, Oct 17, 2017, trustedCertEntry,
  Certificate fingerprint (SHA1): 36:82:F7:AB:. . .:70:B2:6C
  </code></pre>
  
  <p>...but still, whenever I request the SOAP action I'm getting back an HTTP 401 (Unauthorized) — <code>org.springframework.ws.client.WebServiceTransportException: Unauthorized [401]</code>.</p>
  
  <p>Any clue(s)? By the way, I'm pretty much following <a href="http://zoltanaltfatter.com/2016/04/30/soap-over-https-with-client-certificate-authentication/" rel="nofollow noreferrer">this</a> guide. I'm not very familiar with SSL certificates and all that stuff.</p>
  
  <hr>
  
  <p><strong>UPDATE</strong></p>
  
  <p>The SSL handshake is working correctly. I can see how it works by setting the <code>-Djavax.net.debug=all</code> VM option. What's happening now is that, regardless all of this security, the server also needs a username and password.</p>