Oracle Cloud Developer Solutions: Accessing Oracle Process Cloud Service REST API using OAuth | Oracle Community

Oracle Process Cloud service (PCS) provides REST API enabling other applications to integrate with PCS. More details on REST API for Oracle Process Cloud service can be found here. Oracle Process Cloud Service accepts OAuth tokens as an alternative to basic authentication for the REST APIs. In this post we discuss how PCS REST API can be accessed using an OAuth token to create a new business process instance.

The scenario discussed in this blog involves a web application deployed in JCS-SX that triggers a business process (“Funds Transfer Process”) deployed in PCS. The “Funds Transfer” process considered in this blog is a simple business process which validates certain attributes of the incoming request and forwards the request for manual approval if needed. The web application obtains the OAuth token from the OAuth server and passes the token to PCS REST API for authentication.

The following diagram depicts the high level interactions between JCS-SX, PCS and the OAuth server:

This use case considers that both JCS-SX and PCS instances have been provisioned in the same identity domain. When provisioned in the same identity domain, the resources and clients needed for communicating using OAuth are automatically configured along with an OAuth server which is used for obtaining the tokens. You can navigate to “OAuth Administration” tab from “My Services” and see the following OAuth resources and clients registered by default. Please refer to Managing OAuth Resources and Clients for more details.

Note: You need to have an Identity Administrator role to be able to access the “OAuth Administration” page.

Note: Please note the client identifier (Id) (highlighted in red box above) and its respective “secret” (secret) that can be viewed by clicking on the “Show Secret” button of the JCS SX OAuth client. This information will be used by the web application to obtain an access token for the client and access PCS REST API.

The JCS-SX OAuth client is used to invoke the PCS REST API from the web application, hence ensure that the PCS resource is accessible for this client. You can manage the accessibility of the resources by clicking on the “Modify” menu option under the action palette in “Register Client” section against the JCS-SX OAuth client as shown below:

Note: This blog assumes that the business process (“Funds Transfer Process”) is deployed in PCS, the export of the business process is provided in the appendix section for your reference.

With the prerequisites in place we can now proceed to obtain the client access token that would be used by the web application to invoke the PCS REST API. This sample uses the OAuth grant types — client_credentials and password to retrieve the client access token involving the following steps:

  1. Obtain client assertion using the client credentials.
  2. Obtain an access token using the client assertion obtained in the above step

Note: When it comes to making webservice calls within Oracle Platform Services one can use owsm policies for identity propagation and does not necessarily deal with OAuth tokens explicitly.This is just an illustration of how you could use OAuth token for authenticating with PCS without using owsm policies.

These steps are detailed further using specific code snippets.

Store the details of the business process to be invoked and the details required to access the OAuth token server in a HashMap.

Note: To keep things simple for the purpose of this blog, details like client secret, user name , password are stored in a java HashMap, however it is highly recommended to use Oracle Credential Store Framework (CSF) to ensure secure management of credentials. Please look at “References” section at the end of this blog for more information regarding this.

public static HashMap populateMap() {  
HashMap map = new HashMap();
// PCS
map.put("PCS_URL", "https://<PCS_HOST>:443/bpm/api/3.0/processes");
map.put("PCS_PROCESS_DEF_ID", "default~MyApplication!1.0~FundsTransferProcess");
map.put("PCS_FTS_SVC_NAME", "FundsTransferProcess.service");
// OAuth
map.put("TOKEN_URL", "https://<ID_DOMAIN_NAME>.identity.
<DATA_CENTER>.oraclecloud.com/oam/oauth2/tokens");
map.put("CLIENT_ID", "<CLIENT_ID>");
map.put("SECRET", "<SECRET>");
map.put("DOMAIN_NAME", "<ID_DOMAIN_NAME>");
map.put("USER_NAME","<PCS_USER_NAME>");
map.put("PASSWORD","<PCS_USER_PWD>");
return map;
}

public String getOAuthToken() throws Exception{
String token = "";
String authString =
entryMap.get("CLIENT_ID")+":"+entryMap.get("SECRET");

Map clientAssertionMap = getClientAssertion(authString);

token = getAccessToken(authString,clientAssertionMap);

return token;
}

Note: The values specified in the above code for the keys — PCS_PROCESS_DEF_ID, PCS_FTS_SVC_NAME are only for reference. After you deploy the funds transfer business process in PCS, you can retrieve the details of the business process by executing the following curl command and replace the above values appropriately:

curl -u <PCS_USER_NAME>:<PCS_USER_PWD> -H "Content-Type:application/json" -H "Accept:application/json" -X GET https://<PCS_HOST>:443/bpm/api/3.0/process-definitions

The “getOAuthToken” method is implemented to retrieve the client assertion by accessing the OAuth server (token endpoint) and passing client_id:client_secret as a basic authorization header. These details can be obtained from OAuth Administration tab as mentioned in a note above. The following code snippet shows how this can be implemented:

private Map<String,String> getClientAssertion(String authString) throws Exception{  

resource = client.resource( entryMap.get("TOKEN_URL")+"");

ClientResponse res = null;
String payload = "grant_type:client_credentials";

MultiPart multiPart = new MultiPart().bodyPart(new
BodyPart(payload.toString(), MediaType.APPLICATION_JSON_TYPE));

MultivaluedMap formData = new MultivaluedMapImpl();
formData.add("grant_type", "client_credentials");

try {
res =
resource.header("X-USER-IDENTITY-DOMAIN-NAME",
entryMap.get("DOMAIN_NAME"))
.header("Authorization", "Basic " +
DatatypeConverter.printBase64Binary
(authString.getBytes("UTF-8")))
.header("Content-Type", "application/x-www-form-
urlencoded;charset=UTF-8")
.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
.accept(MediaType.APPLICATION_JSON_TYPE)
.post(ClientResponse.class,formData);
} catch (Exception e) {
System.out.println("In catch: "+e);
e.printStackTrace();
throw e;
}

String output = res.getEntity(String.class);
JSONObject newJObject = null;
org.json.simple.parser.JSONParser parser = new
org.json.simple.parser.JSONParser();
try {

newJObject = (JSONObject) parser.parse(output);

} catch (org.json.simple.parser.ParseException e) {
e.printStackTrace();
}

Map<String,String> assertionMap = new HashMap
<String,String>();
assertionMap.put("assertion_token",
newJObject.get("access_token")+"");
assertionMap.put("assertion_type",
newJObject.get("oracle_client_assertion_type")+"");

if (res != null && res.getStatus() != 200) {
System.out.println("Server Problem (getClientAssertion):
"+res.getStatusInfo());
throw new Exception
(res.getStatusInfo().getReasonPhrase());
}
return assertionMap;
}

The above implementation uses a Jersey client to access the token server and obtain a client assertion and client assertion type. Also note that grant_type:client_credentials being passed in the payload. The following code snippet uses the password grant_type to obtain the client access token from the token server by passing in the client assertion obtained earlier along with user name and password.

private String getAccessToken(String authString,Map 
clientAssertionMap) throws Exception{
resource = client.resource(entryMap.get("TOKEN_URL")+"");

String clientAssertionType = (String)
clientAssertionMap.get("assertion_type");
String clientAssertion = (String)
clientAssertionMap.get("assertion_token");

ClientResponse res = null;

MultivaluedMap formData = new MultivaluedMapImpl();
formData.add("grant_type", "password");
formData.add("username", entryMap.get("USER_NAME"));
formData.add("password", entryMap.get("PASSWORD"));
formData.add("client_assertion_type", clientAssertionType);
formData.add("client_assertion", clientAssertion);

try {
res =
resource.header("X-USER-IDENTITY-DOMAIN-NAME",
entryMap.get("DOMAIN_NAME"))
.header("Authorization", "Basic " +
DatatypeConverter.printBase64Binary(
authString.getBytes("UTF-8")))
.header("Content-Type", "application/x-www-form-
urlencoded;charset=UTF-8")
.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
.accept(MediaType.APPLICATION_JSON_TYPE)
.post(ClientResponse.class,formData);
} catch (Exception e) {
e.printStackTrace();
throw e;
}

String output = res.getEntity(String.class);

JSONObject newJObject = null;
org.json.simple.parser.JSONParser parser = new
org.json.simple.parser.JSONParser();
try {

newJObject = (JSONObject) parser.parse(output);

} catch (org.json.simple.parser.ParseException e) {
e.printStackTrace();
}

String token = newJObject.get("access_token")+"";

if (res != null && res.getStatus() != 200) {
System.out.println("Server Problem (getAccessToken):
"+res.getStatusInfo());
throw new Exception
(res.getStatusInfo().getReasonPhrase());
}
return token;
}

The PCS resource can now be accessed using the client access token, the following code snippet invokes the PCS REST API to create a new process instance of the “Funds Transfer” Business Process. The payload consists of the details of the process to be created like process definition id, service name and the input values entered by the user in a JSP page. Please note that the OAuth token obtained in the previous step is being set to the “Authorization” header.

public String invokeFundsTransferProcess(String token,
FundsTransferRequest ftr) throws Exception {

StringBuffer payload = new StringBuffer();
payload.append("{");
  payload.append("\"processDefId\":\""+entryMap.get
("PCS_PROCESS_DEF_ID").toString()+"\",");
payload.append("\"serviceName\":\""+entryMap.get
"PCS_FTS_SVC_NAME").toString()+"\",");
payload.append("\"operation\":\"start\",");
payload.append("\"params\": {");
payload.append("\"incidentId\":\""+
ftr.getIncidentId()+"\",");
payload.append("\"sourceAcctNo\":\""+
ftr.getSourceAcctNo()+"\",");
payload.append("\"destAcctNo\":\""+
ftr.getDestAcctNo()+"\",");
payload.append("\"amount\":"+ftr.getAmount()+",");
String tsfrType;
if(ftr.getTransferType().equals("tparty"))
tsfrType = "intra";
else
tsfrType = "inter";

payload.append("\"transferType\":\""+tsfrType+"\"");
payload.append("}, \"action\":\"Submit\"");
payload.append("}");

MultiPart multiPart = new MultiPart().bodyPart(new
BodyPart(payload.toString(), MediaType.APPLICATION_JSON_TYPE));

resource = client.resource(entryMap.get("PCS_URL").toString());
ClientResponse res = null;
try {
res =
resource.header("Authorization", "Bearer " + token)
.type("multipart/mixed")
.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, multiPart);
} catch (Exception e) {
e.printStackTrace();
throw e;
}

if (res != null && res.getStatus() != 200) {
System.out.println("Server Problem
(PCSRestOAuthClient.invokeFundsTransferProcess):
"+res.getStatusInfo() +" while invoking
"+entryMap.get("PCS_URL").toString());
throw new Exception
(res.getStatusInfo().getReasonPhrase());
}

return res.getStatus()+"";
}

A simple JSP page is used to capture user input and trigger the Funds Transfer Business Process.

Upon successful initiation of the Funds Transfer process, you should be able to see an instance of the process getting created and processed in the “Tracking” page of PCS as shown below:

Known Issues:

Depending on the JDK you use, you might see a “javax.net.ssl.SSLHandshakeException: server certificate change is restricted during renegotiation” error when trying to invoke the PCS REST API from JCS-SX. Please set the following system properties on your JCS-SX and restart the server to work around this issue:

  1. Set “weblogic.security.SSL.minimumProtocolVersion” to “TLSv1.2” in JCS — SaaS Extension and restart JCS — SX
  2. If the problem still persists, set “jdk.tls.allowunsafeservercertchange” to “true” and restart JCS — SaaS Extension

Appendix:

Funds Transfer business process (PCS export) for reference — MyApplication.zip (attached)

References:

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.


Originally published at community.oracle.com on February 19, 2017.

Like what you read? Give venkat y a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.