Skip to content

Lab M02P03-Client

Spring Security supports the X.509 certificate authentication which verifies the identity of a client when using the HTTPS protocol. It is also known as mutual authentication, where a client holds certificate issued for by trusted certificate authority. This lab guides you through client certificate generation, and RestTemplate configuration to communicate with server via SSL over HTTP.

If you want try to configure and implement server side go to m02p03-security-https-lab.

  1. First use openssl to generate client certificate for concrete User identified by certificate CN. Server uses certificate CN to match configured User and Authorities. Client certificate generation for username=user@email.com. Use user@email.com as CN:

      winpty openssl req -new -newkey rsa:4096 -nodes -keyout clientUser.key -out clientUser.csr
    
  2. The client certificate must be signed by trusted authority as server validates certificate during SSL handshake. In the HTTPS server lab you have generated CA key (rootCA.key) and CA certificate (rootCA.crt). Sign client certificate with root CA:

     winpty openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in clientUser.csr -out clientUser.crt -days 365 -CAcreateserial
    
  3. Now, create client store with certificate and key:

      winpty openssl pkcs12 -export -out clientUser.p12 -name "clientUser" -inkey clientUser.key -in clientUser.crt
    

    Copy generated clientUser.p12 into resources folder to have it on classpath. Notice, there is also truststore.p12 file which contains Root CA certificate.

  4. The client in this example is simple scheduled job, which calls server API. The Spring RestTemplate is used. You need to configure Http Client used by RestTemplate to create socket with SSL capability. Spring utilizes Apache HttpClient for RestTemplate implementation. Locate the RestClientConfig class in the project. Define bean of type RestTemplate which uses client certificate for SSL connection creation. Such connection should be accepted by the server as server uses the same Root CA certificate as you used to sign client certificate.

    Hint:

      @Bean
      public RestTemplate restTemplate() throws Exception {
       // Set up SSL context with truststore and keystore
       SSLContext sslContext = new SSLContextBuilder()
               .loadKeyMaterial(
                       keyStore.getURL(),
                       keyStorePassword.toCharArray(),
                       keyStorePassword.toCharArray()
               )
               .loadTrustMaterial(
                       trustStore.getURL(),
                       trustStorePassword.toCharArray()
               )
               .build();
       // Configure the SSLConnectionSocketFactory to use NoopHostnameVerifier
       SSLConnectionSocketFactory sslConFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
       // Use a connection manager with the SSL socket factory
       HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create()
               .setSSLSocketFactory(sslConFactory)
               .build();
       // Build the CloseableHttpClient and set the connection manager
       CloseableHttpClient httpClient = HttpClients.custom()
               .setConnectionManager(cm)
               .build();
       // Set the HttpClient as the request factory for the RestTemplate
       ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
       return new RestTemplate(requestFactory);
     }
    
  5. Notice the RestClientConfig uses properties for keystore and truststore locations. So add following configuration into application.yaml file:

      client:
        ssl:
          key-store: "classpath:clientAdmin.p12"
          key-store-password: "password"
          trust-store: "classpath:truststore.p12"
          trust-store-password: "password"
    
  6. Now, restart the application and check the result. The server should be up and running on localhost port 8443.

Postman as client

You can test API call with mutual TLS, if you set certificates in Postman tool configuration.