Skip to Content
Technical Articles
Author's profile photo Rishabh Dhakarwal

X.509 certificate-based authentication(mTLS) – Communicating with services using SAP destination service(Java)

Written in collaboration withSantosh Kumar

Previous Blogs:

  1. [Blog Series] X.509 certificate-based authentication(mTLS) – Demystified
  2. Generating X.509 certificates of BTP managed services

Upcoming Blog:

  1. Communicating with services using VCAP environment variables(Java)

Introduction:

This is the third blog in this blog post series. This blog will focus on how to communicate to various services which support x.509 certificate authentication using the SAP Destination service.

Content:

  1. Uploading certificate to destination service
  2. Creating destination with certificate authentication
  3. Using the destination in code to call the service endpoint
  4. Summary

1) Uploading certificate to destination service

There are multiple formats supported by SAP Destination Service like JKS, PFX, PEM and P12. For more info, please refer here

Steps to upload certificate:

  1. Go to the SAP BTP subaccount and click on Destinations on the left-hand side
  2. Click on CertificatesSAP%20Destination
  3. Click on Upload Certificate and select the .p12 (or any valid format) certificate we generated in
    the blog Generating X.509 certificates of BTP managed services

    Upload%20Certificate

2) Creating destination with certificate authentication

  1. Once the certificate is uploaded, click on New Destination
  2. Select the Authentication as OAuth2ClientCredentials
  3. Click the Use mTLS for token retrieval for changing client secret to certificate-based input
  4. If the Use mTLS for token retrieval is disabled, enter the Token Service URL to enable it
  5. URL field should contain the base URL of the service with which our microservice will communicate
  6. In the Token Service Key Store Location, we select the certificate uploaded in the previous step
  7. Token Service Key Store Password is the password we set in the blog Generating X.509 certificates of BTP managed services
  8. for creating the certificate
  9. The Token Service URL is different from the regular token URL, it would be mentioned as certurl in the service key file, and then we append /oauth/token to it.Destination
  10. The destination is now ready to be consumed in the code.Connection%20Test

3) Using the destination in code to call the service endpoint

  • SAP Cloud SDK has made it easier to call the destination we configured without any custom call using WebClient or RestTemplate in Java. Refer to this for documentation
  • The SAP Cloud SDK leverages the existing API of HttpClient and applies conveniently managed properties according to the destination configuration.
  • Code sample for sending a POST call to the service endpoint:
    public HttpResponse postUsingCertificateOAuth(HttpDestination httpDestination, String body, String url) {
    	final HttpClient httpClient = HttpClientAccessor.getHttpClient(httpDestination);
        HttpPost post = new HttpPost(url);
    	StringEntity entityInput = null;
    	try {
    		entityInput = new StringEntity(body);
    	} catch (UnsupportedEncodingException e) {
    		LOGGER.error("Json processing exception thrown", e.getMessage(), e.getCause());
    		throw new CertificateOAuthException(e.getMessage());
    	}
    
    	post.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
        post.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);     
        post.setEntity(entityInput);
    
    	HttpResponse response=null;
        try {
        	response = httpClient.execute(post);
    	} catch (IOException e){
    		LOGGER.error(e.getMessage(), e.getCause());
    		throw new CertificateOAuthException(e.getMessage());
    	}
        return response;
    }
  • In the above code:
    • The HttpDestination is the destination we configured above, which can be fetched using the Destination library provided by Cloud SDK
    • The request body is sent to the service endpoint in the POST call
    • URL is the service endpoint to which we send the POST call. It can be fetched from the URL parameter we configured in Destination and appended as per requirement.
    • Similarly, GET and PUT requests can also be sent to the service using HttpClient

4) Summary

In this Blog, we have learnt how to communicate to a service using destination service and certificate-based authentication. The following blog will cover communicating to services bound to our application using VCAP environment variables.

Upcoming Blogs:

  1. Communicating with services using VCAP environment variables(Java)

Please let us know if you find this content helpful and share any inputs and feedback.

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Satish Kumar Kara
      Satish Kumar Kara

      Hi Rishabh,

      Nice writeup..

      Do you have any reference on how to do this without SAP Cloud SDK?

      Best Regards, Satish

      Author's profile photo Rishabh Dhakarwal
      Rishabh Dhakarwal
      Blog Post Author

      You can refer to this code and use the RestTemplate to call the endpoints:

      import javax.net.ssl.SSLContext;
      import com.sap.cloud.security.mtls.SSLContextFactory;
      import org.apache.http.client.HttpClient;
      import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
      import org.apache.http.impl.client.HttpClients;
      void sampleMethod(){
         HttpClient client = null;
         SSLContext sslContext;
         try {
              sslContext = SSLContextFactory.getInstance()
                          .create(this.envVariable.getCertificateChain(),
      					this.envVariable.getPrivateKey());
             } catch (GeneralSecurityException | IOException e) {
      	logger.error("Error while create service ssl context :{}", e.getMessage());
      	Throwable th = e.getCause();
      	throw new Exception(th.getMessage(), th.getCause());
             }	
      		
         client = HttpClients.custom()
      	   .setSSLContext(sslContext)
      	   .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext))
      	   .build();
         final HttpClient httpClient = client;
         HttpComponentsClientHttpRequestFactory requestFactory = new 
                               HttpComponentsClientHttpRequestFactory();
         requestFactory.setHttpClient(client);
         RestTemplate template = new RestTemplate(requestFactory);
      }