I am calling a webservice that requires client certificate authentication.
If I specify a Java keystore containing a single certificate (the client certificate the servi
The links that Jakub provides in his response lead you to the answer, but I wanted to post a simpler response here, since we struggled with this problem for quite a while before finally getting something that worked.
We have the case where there are several certificates available to use, and we need to use the one that has a specific alias to perform our connection. We did this by creating our own KeyManager implementation which passes through most of its functionality to the default X509KeyManager but has functionality to select exactly the correct alias to use when the connection is performed.
First the key manager we created:
public class FilteredKeyManager implements X509KeyManager {
private final X509KeyManager originatingKeyManager;
private final X509Certificate[] x509Certificates;
public FilteredKeyManager(X509KeyManager originatingKeyManager, X509Certificate[] x509Certificates) {
this.originatingKeyManager = originatingKeyManager;
this.x509Certificates = x509Certificates;
}
public X509Certificate[] getCertificateChain(String alias) {
return x509Certificates;
}
public String[] getClientAliases(String keyType, Principal[] issuers) {
return new String[] {"DesiredClientCertAlias"};
}
All other methods required for implementation are passthroughs to originatingKeyManager
.
Then, when we actually set up the context:
SSLContext context = SSLContext.getInstance("TLSv1");
context.init(new KeyManager[] { new FilteredKeyManager((X509KeyManager)originalKeyManagers[0], desiredCertsForConnection) },
trustManagerFactory.getTrustManagers(), new SecureRandom());
Hope that makes it clear, and works for anyone else trying to solve this problem.