Calling RestTemplate APIs using custom Certificate and Key

3.9k Views Asked by At

I am calling an external API via RestTemplate that requires SSL Certificate. Already the external API provider has provided me with the certificate file (company.crt) and its key file (company.key). While adding the certificate, key and password in Postman, I am able to successfully call the API. But when I am calling using RestTemplate inside a SpringBoot project, even after adding SSLContext, I am receiving an error.

The steps I have followed:

Created a company.p12 store file from company.crt and company.key file using openssl:

openssl pkcs12 -export -name servercert -in company.crt -inkey company.key -out company.p12

Converted company.p12 to company.jks store file using Keytool:

keytool -importkeystore -destkeystore company.jks -srckeystore company.p12 -srcstoretype pkcs12 -alias companycert

Have created the config inside application.properties file as, after placing company.jks inside resource folder of SpringBoot project:

http.client.ssl.trust-store=classpath:company.jks
http.client.ssl.trust-store-password=Password

Then, I have created a configuration for RestTemplate as:

@Value("${http.client.ssl.trust-store}")
private Resource keyStore;
@Value("${http.client.ssl.trust-store-password}")
private String keyStorePassword;

@Bean
RestTemplate restTemplate() throws Exception {

    SSLContext sslContext = new SSLContextBuilder()
                                 .loadTrustMaterial(
                                     keyStore.getURL(),
                                     keyStorePassword.toCharArray()
                                 ).build();

    SSLConnectionSocketFactory socketFactory = 
              new SSLConnectionSocketFactory(sslContext);

    HttpClient httpClient = HttpClients.custom()
              .setSSLSocketFactory(socketFactory).build();

    HttpComponentsClientHttpRequestFactory factory = 
               new HttpComponentsClientHttpRequestFactory(httpClient);

    return new RestTemplate(factory);

}

Calling an external APIs as:

@Autowired
RestTemplate restTemplate;

@GetMapping("/api")
public Object callAPI() {

    final String ENDPOINT = "https://some-api.domain.com:8533/api/key/";
    Object response = restTemplate.exchange(ENDPOINT, HttpMethod.GET, request, Object.class);
    return response;

}

The error after calling an API via RestTemplate:

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
1

There are 1 best solutions below

0
On

Got it resolved:

application.properties configuration: Add Key store properties

http.client.ssl.trust-store=classpath:company.jks
http.client.ssl.trust-store-password=Password

http.client.ssl.key-store=classpath:company.p12
http.client.ssl.key-store-password=Password

Then, inside RestTemplate configuration:

@Bean
RestTemplate restTemplate() throws Exception {

    TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

    SSLContext sslContext = new SSLContextBuilder()
        .loadTrustMaterial(
            trustStore.getURL(),
            trustStorePassword.toCharArray(), acceptingTrustStrategy
         )
         .loadKeyMaterial(
             keyStore.getURL(), 
             keyStorePassword.toCharArray(), 
             keyStorePassword.toCharArray())
         .build();

    SSLConnectionSocketFactory socketFactory = 
        new SSLConnectionSocketFactory(sslContext);

    HttpClient httpClient = HttpClients.custom()
        .setSSLSocketFactory(socketFactory).build();

    HttpComponentsClientHttpRequestFactory factory = 
        new HttpComponentsClientHttpRequestFactory(httpClient);

    return new RestTemplate(factory);

}