Page 1 of 1

How to add client certificate in the htttp plugin

PostPosted: Tue Nov 14, 2023 3:34 pm
by Juan Etec
Hi,
using the http plugins, is there any way to add client certificates?
I have done in postman adding myCertificate.pfx and my password, but I have no idea to develop it in servoy.

Thanks

Re: How to add client certificate in the htttp plugin

PostPosted: Thu Nov 16, 2023 11:34 am
by Joas
This is not possible with the http plugin, but you can do it with the Apache http client using inline java.
I needed to do the same thing to call a couple of soap webservices, so I created a method for that.

Here a simplified version:
Code: Select all
/**
* @param {XML} xml
* @param {String} url
* @param {String} [certPath] The path of the certificate file
* @param {String} [certPassword]
* @param {*} [httpHeaders] for example: '{"Authorization":"Basic abcdef","SOAPAction":"SOAPACTION"}'
* @param {String} [username] for basic authentication
* @param {String} [password]
*
* @return {String}
*
* @properties={typeid:24,uuid:"86F518A3-472C-4F6B-9B70-2B6D3749AC37"}
*/
function callSoap(xml, url, certPath, certPassword, httpHeaders, username, password) {

   //Save references to java classes
   var FileInputStream = Packages.java.io.FileInputStream;
   var StandardCharsets = Packages.java.nio.charset.StandardCharsets;
   var KeyStore = Packages.java.security.KeyStore;
   var SecureRandom = Packages.java.security.SecureRandom;
   var Base64 = Packages.java.util.Base64;

   var KeyManagerFactory = Packages.javax.net.ssl.KeyManagerFactory;
   var SSLContext = Packages.javax.net.ssl.SSLContext;

   var HttpPost = Packages.org.apache.http.client.methods.HttpPost;
   var HttpClients = Packages.org.apache.http.impl.client.HttpClients;
   var StringEntity = Packages.org.apache.http.entity.StringEntity;
   var EntityUtils = Packages.org.apache.http.util.EntityUtils;
   var ByteArrayOutputStream = Packages.java.io.ByteArrayOutputStream;

   //Create http client
   var httpClient;

   if (certPassword && certPath) {
      //Add client certificate
      certPassword = new java.lang.String(certPassword);
      var inputStream = new FileInputStream(certPath);
      var kmf = KeyManagerFactory.getInstance("SunX509");
      var keyStore = KeyStore.getInstance("PKCS12", "SunJSSE");
      keyStore.load(inputStream, certPassword.toCharArray());
      kmf.init(keyStore, certPassword.toCharArray());

      var ctx = SSLContext.getInstance("SSL");
      ctx.init(kmf.getKeyManagers(), null, new SecureRandom());

      httpClient = HttpClients.custom().setSSLContext(ctx).build();
      //For older version of httpclient: httpClient = HttpClients.custom().setSslcontext(ctx).build();
   } else {
      httpClient = HttpClients.createDefault();
   }

   //Create request
   var request = new HttpPost(url);

   //Set default headers
   request.setHeader("Accept", "text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2");
   request.setHeader("Content-Type", "text/xml; charset=UTF-8");
   request.setHeader("Accept-Encoding", "gzip,deflate");
   request.setHeader("MIME-Version", "1.0");

   //Add basic authentication
   if (username && password) {
      var up = new java.lang.String(username + ":" + password);
      var authentication = new java.lang.String(Base64.getEncoder().encode(up.getBytes(StandardCharsets.UTF_8)));
      request.setHeader("Authorization", "Basic " + authentication);
   }

   //Add http headers to the request
   if (httpHeaders) {
      for (var i in httpHeaders) {
         request.setHeader(i, httpHeaders[i]);
      }
   }

   //Set the xml as body content of the post
   request.setEntity(new StringEntity(xml));

   //Output request as a string in developer
   if (application.isInDeveloper()) {
      var requestHeaders = request.getRequestLine() + "\n" + (request.getAllHeaders().join("\n"));

      var outputStream = new ByteArrayOutputStream();
      request.getEntity().writeTo(outputStream);
      var strMsg = requestHeaders + "\n" + outputStream.toString();
      application.output("====REQUEST START====" + utils.dateFormat(application.getServerTimeStamp(), "yyyy-MM-dd HH:mm:ss") + "\n" + strMsg + "\n====REQUEST END====");
   }

   //Execute request
   var response = httpClient.execute(request);

   //Handle response
   var entity = response.getEntity();

   if (entity != null) {
      //Save the reponse body as string
      var responseString = EntityUtils.toString(entity, "UTF-8");

      if (responseString) {
         //Get rid of the soap envelope, just get the body xml
         var bodyMatch = responseString.replace(/\n/g, "").match(/<.*:body[^>]*>(.*)<\/.*:body>/i);

         if (bodyMatch) {
            return bodyMatch[1];
         } else {
            return responseString;
         }
      }
   }
   return null;
}

To run this, you need to download the httpclient and httpcore jars and put them in your plugins folder.

Re: How to add client certificate in the htttp plugin

PostPosted: Fri Nov 17, 2023 10:38 am
by Juan Etec
Hi Joas,
thanks for your reply.
Is really helpful.
I didn't know that it doesn't work, with the http plugin.
I owe you a couple of beers in Gran Canaria. :lol: