Search code examples
javaspringx509certificateresttemplateclient-certificates

What is the right way to send a client certificate with every request made by the resttemplate in spring?


i want to consume a REST service with my spring application. To access that service i have a client certificate (self signed and in .jks format) for authorization. What is the proper way to authenticate against the rest service?

This is my request:

public List<Info> getInfo() throws RestClientException, URISyntaxException {

    HttpEntity<?> httpEntity = new HttpEntity<>(null, new HttpHeaders());

    ResponseEntity<Info[]> resp = restOperations.exchange(
            new URI(BASE_URL + "/Info"), HttpMethod.GET, 
            httpEntity, Info[].class);
    return Arrays.asList(resp.getBody());
}

Solution

  • Here is example how to do this using RestTemplate and Apache HttpClient

    You should define your own RestTemplate with configured SSL context:

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
        char[] password = "password".toCharArray();
    
        SSLContext sslContext = SSLContextBuilder.create()
                .loadKeyMaterial(keyStore("classpath:cert.jks", password), password)
                .loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
    
        HttpClient client = HttpClients.custom().setSSLContext(sslContext).build();
        return builder
                .requestFactory(new HttpComponentsClientHttpRequestFactory(client))
                .build();
    }
    
     private KeyStore keyStore(String file, char[] password) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        File key = ResourceUtils.getFile(file);
        try (InputStream in = new FileInputStream(key)) {
            keyStore.load(in, password);
        }
        return keyStore;
    }
    

    Now all remote calls performed by this template will be signed with cert.jks. Note: You would need to put cert.jks into your classpath

    @Autowired
    private RestTemplate restTemplate;
    
    public List<Info> getInfo() throws RestClientException, URISyntaxException {
        HttpEntity<?> httpEntity = new HttpEntity<>(null, new HttpHeaders());
    
        ResponseEntity<Info[]> resp = restTemplate.exchange(
                new URI(BASE_URL + "/Info"), HttpMethod.GET, 
                httpEntity, Info[].class);
        return Arrays.asList(resp.getBody());
    }