Hello,
Today we are going to see how we can invoke a REST API which is secured with private key & certificate which requires two way SSL for successful invocation.
Before starting development what we need:
Today we are going to see how we can invoke a REST API which is secured with private key & certificate which requires two way SSL for successful invocation.
Before starting development what we need:
- Certificate.pfx file
- This PFX file contain a CERTIFICATE AND KEY, which will be used for two way SSL
- REST API URL like "https://SERVERURL/URL/connect/token"
JAVA implementation:
We need to use below external JAR's for making HTTP Call.
Below is sample JAVA code for same:
package com.api.client;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
public class APIClient {
private static final Logger LOG = Logger.getLogger(APIClient.class
.getName());
private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
private static final String CLIENT_KEYSTORE_PATH = "ABS PATH\\Certificate.pfx";
private static final String CLIENT_KEYSTORE_PASS = "Password";
/*REQUEST PARAMS*/
private static final String SCOPE = "SCOPE";
private static final String client_secret = "client_secret ";
private static final String grant_type = "grant_type";
private static final String client_id = "client_id ";
/*REQUEST PARAMS*/
private static final String SERVICEURL = "https://SERVERURL/URL/connect/token";
private static final String proxyServerURL = "PROXY SERVER NAME";
private static final String proxyServerPort = "80";
public static void main(String[] args) throws Exception {
System.out.println("API RESPONSE"
+ (requestTimestamp(SCOPE, client_secret, grant_type,
client_id, SERVICEURL, CLIENT_KEYSTORE_PATH,
CLIENT_KEYSTORE_PASS, proxyServerURL, proxyServerPort,
"0")));
}
/* THIS METHOD WILL BE CALLED FROM OSB JAVA CALLOUT, OSB JAVA CALLOUT WILL SEND ALL PARAMETERS*/
public static String requestTimestamp(String Scope, String client_secret,
String grant_type, String client_id, String SERVICEURL,
String PFX_location, String PFX_Password, String proxyServerURL,
String proxyServerPort, String withProxy) throws Exception {
String JsonResponse = "";
/*IN CASE YOU ARE GOING TO INVOKE API WITH PROXY SERVER, IN CASE YOU DON'T NEED ANY PROXY SERVER REMOVE THIS LINE CODE & IT'S MAPPING*/
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
proxyServerURL, Integer.parseInt(proxyServerPort)));
URL url = new URL(null, SERVICEURL,
new sun.net.www.protocol.https.Handler());
String requestParams = "scope=" + SCOPE + "&grant_type=" + grant_type
+ "&client_id=" + client_id + "&client_secret="
+ java.net.URLEncoder.encode(client_secret);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection(proxy);
setConnectionProps(con);
SSLContext context = getSSLSocketFactory(PFX_location, PFX_Password);
SSLSocketFactory sockFact = context.getSocketFactory();
con.setSSLSocketFactory(sockFact);
// Send the request
OutputStream outputStream = con.getOutputStream();
outputStream.write(requestParams.getBytes("UTF-8"));
outputStream.close();
// Check for errors
int responseCode = con.getResponseCode();
InputStream inputStream;
if (responseCode == HttpURLConnection.HTTP_OK)
{
inputStream = con.getInputStream();
}
else {
inputStream = con.getErrorStream();
}
// Process the response
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(inputStream));
while ((JsonResponse = reader.readLine()) != null)
{
return JsonResponse;
}
inputStream.close();
return null;
}
private static void setConnectionProps(HttpsURLConnection con)
throws Exception {
con.setRequestProperty("Connection", "close");
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setConnectTimeout(30000);
con.setReadTimeout(30000);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
con.setRequestProperty("Accept", "application/json");
}
private static SSLContext getSSLSocketFactory(String PFX_location,
String PFX_Password) throws Exception {
SSLContext context = null;
File pKeyFile = new File(PFX_location);
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, PFX_Password.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, PFX_Password.toCharArray());
context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null,
new SecureRandom());
return context;
}
}
THIS PIECE OF CODE WILL RETURN YOU API RESPONSE WITH 2-WAY SSL.
In this piece of code method "getSSLSocketFactory" will associate key & certificate with the request.
- Export this JAVA project into one JAR file, This JAR is going to be used inside OSB JAVA CALLOUT.
- Before OSB development, we have to configure CLASSPATH with these JAR files that we used in JAVA project so when OSB make a JAVA CALLOUT over our newly created JAR, it don't throw CLASS NOT FOUND EXCEPPTION.
OSB SERVER CONFIGURATION:
1.Copy jars at any location on SOA Server, in DEV server cases, it is on "/https_Rest_jar_files"
2.Also copy "Certificate.pfx" at same location.
3.Change values in DVM
4. Open the file %DOMAIN_HOME/BIN% “setDomainEnv” in edit mode.
5.POST_CLASSPATH="/https_Rest_jar_files/commons-codec-1.9.jar${CLASSPATHSEP}/https_Rest_jar_files/commons-logging-1.2.jar${CLASSPATHSEP}/https_Rest_jar_files/httpclient-4.5.2.jar${CLASSPATHSEP}/https_Rest_jar_files/httpcore-4.4.4.jar${CLASSPATHSEP}${POST_CLASSPATH}"
export POST_CLASSPATH
6.restart server.
OSB SIDE DEVELOPMENT:
Now we need to design one OSB project with OSB proxy & pipe line which will invoke this REST API CLIENT JAR.
Enjoy reading!!!
Have any question, post me!!!
We recommend the use of RSA based authentication for Bot applications. Perform this authentication process using client certificates or a JSON Web Token. REST API callers must authenticate to the Pod and the Key Manager separately. Compile And Run Java Programs
ReplyDeleteHi, I've followed the same as mentioned above; but it throws error saying "java.io.IOException: keystore password was incorrect".
ReplyDeleteThe pfx certificate and password are valid and works fine when invoke the api from postman.
any help?
Thank you
ReplyDeleteHi Sandeep, Do you have a few min for a quick call on this PFX Certificate key. We have an issue and looking for a solution. It would be great if you can connect. Thanks
ReplyDeleteSafeeq
Hi,
DeleteYou can post your question here, will try to answer... Not possible to join any call...sorry
outdated code, sun.net.www.protocol.jar.Handler is obsolete and there is no replacement
ReplyDelete