The Oracle Sales Cloud provides an extensive set of features for extending the user interface, the underlying data model, and allows the use of Groovy scripts to extend or adjust the default business logic. If customers have requirements that go beyond these capabilities, Java Cloud Service is a viable option to build new user interface allowing a seamless UI level integration (see the samples here). If an extension is not driven by UI requirements but rather backend orchestration and integration needs, introducing the Oracle SOA stack is a logical option to consider.
This article describes how business logic implemented in Oracle SOA Suite can be invoked in a secure way while ensuring that the additional logic in SOA Suite can execute in the Sales Cloud user's security context.
For simplicity, we are showing here a basic SOA composite with a BPEL component that is doing nothing than receiving a JWT token from the Sales Cloud and then calling back a web service in the Sales Cloud leveraging this token. Here is an overview of the composite:
The BPEL process is exposed as a SOAP service on the left side of the diagram. We have secured this SOAP service by attaching the OWSM policy oracle/wss11_username_token_with_message_protection_service_policy. This makes sure the SOA composite can only be invoked by an authorised service client. You can also see that the reference towards the SalesCloud service on the right side has no policy attached (there is no lock icon). This is intentional since we will pass on the JWT token programatically in the HTTP header and don't use an OWSM policy for that.
For setting the outbound HTTP header we are following the approach as outlined in this blog. The first step is to allow for passing on the Authorization Header on the reference. This needs to be done in the composite.xml by adding the oracle.webservices.http.headers property:
<reference name="UserDetailsService" ui:wsdlLocation="https://<sales cloud server>/hcmPeopleRolesV2/UserDetailsService?WSDL"> <binding.ws port="http://xmlns..." location="https://..." soapVersion="1.1"> <property name="oracle.webservices.http.headers">Authorization</property> </binding.ws> </reference>
With that the BPEL component is enabled to pass the token via a toProperty in the invoke against any Sales Cloud service. In our example we are using the UserDetailsService that can basically do a 'who-am-I' call, but that could be any other web service exposed by the Sales Cloud as well:
The interesting bits here are the construction of the Authentication string and the invoke including the inputProperty:
<assign name="Assign_AuthenticationString"> <copy> <from expression="concat('jwt ',bpws:getVariableData('inputVariable','payload','/client:process/client:input'))"/> <to variable="AuthenticationString"/> </copy> </assign> <invoke name="Invoke_UserDetailsService" inputVariable="Invoke1_findSelfUserDetails_InputVariable" outputVariable="Invoke1_findSelfUserDetails_OutputVariable" partnerLink="UserDetailsService" portType="ns1:UserDetailsService" operation="findSelfUserDetails" bpelx:invokeAsDetail="no"> <bpelx:inputProperty name="Authorization" variable="AuthenticationString"/> </invoke> </sequence>
So the Authentication string is a simple concatenation of 'jwt<space>' and the actual token. The inputProperty is then translated into a HTTP header when invoking the actual endpoint.
Note that with SOA 12c the invoke looks slightly different:
<bpelx:toProperties> <bpelx:toProperty name="Authorization" variable="AuthorizationString"/> </bpelx:toProperties>
After deploying this composite on the SOA server we can now go ahead and register the web service in the Sales Cloud:
The Sales Cloud application composer is smart and recognises that the SOA service is secured through the attached OWSM policy and hence asks for a credential key. Obviously this will be a fixed user existing in the SOA infrastructure, but since we provide the JWT token in the payload of the invocation SOA will still be able to switch identity for any calls back into the Sales Cloud.
The last step is to refer to the registered web service in a Groovy script to trigger the service invocation. It is entirely up to the use case if this might be in an object trigger, a script attached to a custom button in the UI, or anywhere else where Groovy scripts can be executed. And obviously it's also up to the use case what should go into the payload. At a minimum one would usually propagate the key of the object so that SOA has the required context e.g. pass on an opportunity ID to first do a message enrichment call back into the Sales Cloud (e.g. to retrieve the entire opportunity record) and then do any subsequent processing either back into the Sales Cloud or to other external systems.
For an invocation that does nothing but passing on the JWT token like in our sample here the Groovy script only needs a single line:
Finally, here is what happens in our BPEL process after it's been triggered by the Sales Cloud:
You can see that in this example the JWT token was passed as the only parameter to the process and then constructs the AuthenticationString. This is used in the invocation of the Sales Cloud service and the Sales Cloud is able to identify the user based on the token alone.
It is important to understand where the approach outlined above is applicable and where other options would be a better choice.
While the ability to leverage the entire SOA Suite stack for implementing additional logic for the Sales Cloud opens up new possibilities, there is a fundamental prerequisite that needs to be met: the SOA service must be reachable from the Sales Cloud. As of today when the SOA environment is hosted on-premise in the customer's data center, this would require exposing the service in the public internet or have a VPN solution in place. Going forward, we will see new Oracle Cloud Services that allow running the SOA infrastructure in the cloud as well and that will help addressing this limitation.
From a security perspective, the advantage of this approach is that SOA does not have to know the identity of the user in the Sales Cloud since this is wrapped into the JWT token, but SOA is still able to execute in the context of the Sales Cloud user. While this simplicity is great on the one hand as it requires not setup on the infrastructure level, there are other limitations such as the fact that the JWT token per definition has a limited life time of typical a few hours. This means that if there is a long running process in SOA, the token might expire at some point and SOA has no way of either getting a new token from the Sales Cloud or even constructing a new token. For such a scenario a SAML based solution would be better suited. Another aspect is that a JWT token could theoretically be abused if somebody gets hold of it in some way since the Sales Cloud cannot verify the caller providing a JWT token, it needs to trust any service client that has a valid token.
This article discussed how the Oracle Sales Cloud can invoke services running on Oracle SOA suite in way so that SOA suite can execute in the Sales Cloud user's security context. It also discussed important limitations and security concerns customers need to be aware of if they consider implementing such a solution.