2

I have a Java websocket client using the javax.websocket libraries which currently looks like this:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.setDefaultMaxTextMessageBufferSize(BUFFER_SIZE);
container.connectToServer(this, ENDPOINT_URI);

Now I have the requirement, that the client needs to supply a client certificate to the server. How can this be accomplished?

Alig
  • 314
  • 4
  • 17

2 Answers2

3

I found a solution, so I answer my own question:

The WebsocketContainer can be configured with an ClientEndpointConfig. This allows to set a custom SSLContext. Then client certificate must be attached to the SSLContext. Code:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.setDefaultMaxTextMessageBufferSize(BUFFER_SIZE);
container.connectToServer(new PojoEndpointClient(this, new ArrayList<>()), createClientConfig(), endpointURI);

And the ClientEndpointConfig can be constructed like this:

private ClientEndpointConfig createClientConfig() throws KeyManagementException, UnrecoverableKeyException,
 NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
    ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create();
    ClientEndpointConfig config = builder.decoders(new ArrayList<>()).encoders(new ArrayList<>())
            .preferredSubprotocols(new ArrayList<>()).build();
    SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(clientCert.toFile(), clientCertPassword,
            clientCertPassword, (aliases, socket) -> aliases.keySet().iterator().next()).build();
    config.getUserProperties().put(Constants.SSL_CONTEXT_PROPERTY, sslContext);
    return config;
}

This will present the client certificate to the server when establishing the websocket connection.

Alig
  • 314
  • 4
  • 17
  • 1
    Constants.SSL_CONTEXT_PROPERTY is missing when the method is implemented. What library did you use? – misterbaykal Apr 11 '19 at 06:57
  • 1
    Its from Apache Tomcat: org.apache.tomcat.websocket.Constants – Alig Apr 12 '19 at 14:20
  • 1
    Note that `SSLContexts.custom()` doesn't exist in recent versions, instead use `org.apache.http.ssl.SSLContextBuilder` from `org.apache.httpcomponents:httpcore`: ```java SSLContext sslContext = SSLContextBuilder .create() .loadKeyMaterial(new File(p12File), p12Password, p12Password) .build(); clientConfig.getUserProperties().put(Constants.SSL_CONTEXT_PROPERTY, sslContext); ``` – Michael Yakobi Nov 29 '20 at 22:09
0

I am not sure what certificate you are talking about, but probably you mean SSL/TLS certificate. In this case you need just to use wss client(eg nv-websocket-client), which will handle all ssl/tls under the hood.

See also answer: minimal java8 nio secure websocket client (wss)

Rudziankoŭ
  • 10,681
  • 20
  • 92
  • 192
  • SSL/TLS is not the issue. We already connect using wss. But additionaly, I need to provide a client certificate. – Alig Aug 09 '18 at 10:47