Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
engswee
Active Contributor

Introduction

OAuth 2.0 is becoming a common authentication method to access REST-based services (i.e. Concur, Google, SFDC). Unfortunately, different organizations might have different implementations of OAuth 2.0 and thus there is lack of a standard approach to it. According to the blog Authenticating from HANA Cloud Integration, HCI currently only supports the Client Credentials Grant Type for OAuth 2.0.

Unlike PI, fortunately HCI has a flexible pipeline processing based on Apache Camel and this allows for easy inclusion of intermediate request-reply calls before the message reaches the final target.

In this blog, I will share how we can take advantage of HCI's flexible iFlow model to design a solution using custom OAuth 2.0 authentication that has yet to be supported by HCI natively. For the example, I will implement Concur's OAuth 2.0 Native Authorization Flow to retrieve an access token prior to accessing Concur's REST API. This is analogous to Option 3 of the following article detailing the support for Concur's OAuth 2.0 in PI's REST adapter.

PI REST Adapter - Connect to Concur

Component Details

As HCI is a cloud solution with automatic rolling updates, these steps are valid for the following versions and may change in future updates.

Below are component versions of the tenant and Eclipse plugins.

HCI Tenant Version: 2.8.5

Eclipse Plugin Versions: Adapter 2.11.1, Designer 2.11.1, Operations 2.10.0

iFlow Design

Below is the design of the iFlow for this example. For simplicity sake, it uses a start timer to trigger the flow once it is deployed. The target recipient is an HTTP server that logs the message posted to it.

Following is an overview of the various sections involved in the flow, which will be elaborated further.

  • Step 1 - Retrieve the user credentials and execute call to Concur token endpoint to retrieve the token
  • Step 2 - Extract the access token value from response of previous call and formulate the HTTP header for authentication using OAuth
  • Step 3 - Execute call to Concur REST API
  • Step 4 - Send REST API response to HTTP target

Design & Configuration

In this section, I will elaborate further on the design and configuration of each step.

Step 1

In order to retrieve an OAuth 2.0 access token from Concur, we first need to perform an HTTP GET call to its token endpoint. This token endpoint expects basic authentication which consists of the Base64 encoded value of the credential (userID:password) in the HTTP header. Additionally, the consumer key needs to be also passed in the HTTP header.

In order to achieve this, we first make use of the User Credentials artifact to securely store and deploy the user ID and password. For more details on that, refer to the following blog on how to configure and deploy the artifact. For this example, I have deployed the credentials under the artifact name ConcurLogin.

Building your first iFlow - Part 4: Configuring your credentials

Within the iFlow, this credential will be retrieved using a Groovy script by utilizing the SecureStoreService API.

Below is the logic for the Groovy script. Basically it retrieves the user credential from artifact ConcurLogin. It then encodes the login credentials in Base64. Finally it sets the two required HTTP header fields (note that I have deliberately modified the actual value of the consumer key).


import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import javax.xml.bind.DatatypeConverter;
import com.sap.it.api.ITApiFactory;
import com.sap.it.api.securestore.SecureStoreService;
import com.sap.it.api.securestore.UserCredential;
def Message processData(Message message) {
  def service = ITApiFactory.getApi(SecureStoreService.class, null);
  def credential = service.getUserCredential("ConcurLogin");
  if (credential == null){
    throw new IllegalStateException("No credential found for alias 'ConcurLogin'");
  }
  String user = credential.getUsername();
  String password = new String(credential.getPassword());
  def credentials = user + ":" + password;
  def byteContent = credentials.getBytes("UTF-8");
  // Construct the login authorization in Base64
  def auth = DatatypeConverter.printBase64Binary(byteContent);
  message.setHeader("Authorization", "Basic " + auth);
  message.setHeader("X-ConsumerKey", "xxxx");
  return message;
}





Subsequently, the message is processed by a Request-Reply step that calls the token endpoint using the following channel configuration.

Step 2

After the call to the token endpoint, the token is provided in an XML response as shown below.

We will then use a Content Modifier step to extract the token value via XPath and store it in a property.

To access Concur's REST API, it requires the OAuth token to be specified in the HTTP header as shown below:-


Authorization: OAuth <token_value>






Once we have the token value, it will be used in the following Groovy script logic to set the HTTP header.


import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
  // Get the OAuth token value from the properties
  def map = message.getProperties();
  def token = map.get("token");
  // Remove the Consumer key from previous header
  map = message.getHeaders();
  map.remove("X-ConsumerKey");
  // Set the OAuth authorization credentials
  message.setHeader("Authorization", "OAuth " + token);
  return message;
}



Step 3

Once the OAuth token has been set in the HTTP header, the subsequent call to Concur's REST API is configured as an HTTP receiver channel. In the example below, I configure the channel to use Concur's Extract API to retrieve an extract file.

Step 4

Finally, the response of the REST API call is sent to a target HTTP logging system. For the example, I have used the tool described in the following blow.

Testing: Test Tools...Part 1 *HTTP *

Testing Results

Once the iFlow has been completed and deployed, the interface will be triggered and the outcome can be seen on the POST Test Server log. As shown below, we were able to retrieve the extract file using Concur's Extract API utilizing a custom OAuth 2.0 authentication.

Conclusion

As shown above, HCI's flexible pipeline allows us to built quite complex iFlows. Together with custom Groovy scripts, it allows for a lot of possibility to design a customized solution. In this example, I have shown how it is utilized to built a custom OAuth 2.0 authentication that has not been supported by HCI natively. These days, more and more services are using two-step approaches involving tokens and session IDs, and as such having such a flexible pipeline comes in very handy to tackle those integration requirements.

16 Comments
Labels in this area