Introduction:


OAuth, SAML & JWT etc..,
are now becoming the common way of authenticating web, mobile and desktop applications . The benefits these protocols brings in terms of  security, simplicity and reduced complexity is immense which obviously makes a good choice for applications to implement these protocols as they way of authentication.
HCI(HCP-IS) with its flexible pipeline makes it simpler to call applications which uses the above protocols.  blog over Oauth here nicely articulates how to develop custom OAuth authentication with an initial token. In this blog, I want to share how we could make the OAuth Authentication more dynamic. Getting the initial access tokens, checking their validity, reusing the valid tokens and renewing the expired tokens. i.e.
  • Get the Initial access tokens. (A token always has a validity and a refresh token associated with it. After the the validity period, the initial access token is no longer valid to access the app. A new token has to be requested using the refresh token associated with the initial access token to access the app)
  • Checking the validity of the initial access token and reuse the same token if it is still valid ( its of no use and more over a performance overhead to every time request a new token while we could use the initial access token to access the app , which is still valid.
  • Re-new the token using the refresh token, if the validity is expired.
Along with the above topics, I would like to also share about the usage of data stores & configuring dynamic endpoints using variables in an endpoint(url).
Template of the entire project could be downloaded from github.
Above project is for calling a Rest service to search products on-premise Hybris e-commerce system using OAuth authentication.  Further more, products specific to a particular customer group are retrieved by specifying the dynamic customer group in the product search service uri.
Step 0: SAP API calls the iflow endpoint which has adapter type as HTTPs as sender communication channel.
https://<host>:<port>/http/products/search ( more info on configuring sender https adapter here )
Step 1: Get the Initial access tokens.
Mainflow further calls two sub flows to check if there is already a token in data store. if yes, then the flow continues to check the validity of the token found in data store other wise a new call is made to fetch the initial access tokens and save them in data store.
Content Modifier:  username and password is hardcoded to keep this iflow simple here . These credentials are used to authenticate the resource owner and fetch the OAuth tokens from Hybris. ( Instead of Hardcoding username and password, you can deploy Secure Parameter artifacts and use a script to fetch them and use in your iflow. Other alternate is to use OAuth2 Authentication artifact ).
         
Data Store: You use a datastore operation to write/read a complete message to/from HCI database.  By default these messages are stored for 90 days and are deleted after 90 days. more info on data stores here
  Here the data store code_hashmap with “Get” operation is used to get the message stored    on HCI with the Entry ID as “test1@hybris.com” . If the data store is not found or the data store   is empty, an exception is raised and Iflow is terminated without further processing.
Apart from ${header.<name>}, you could also use an Xpath expression ${xpath.<xpath>}to dynamically generate the entry ID from an element in the message.
We will discuss later where and how the entry is written to data store later in this blog.
message retrieved from data store with entry id test1@hybris.com has the following content:
As discussed above when the date store is not found an exception is raised which further triggers the exception subprocess which further calls a sub flow to fetch the initial access tokens.
Router:This Router after the get operation checks whether the message has a value for attribute “access_token” .
Initial OAuth Tokens ( Get Token : Default route and exception subprocess in Mainflow):This subflow calls a REST service on Authorization Server and gets the initial access tokens. Receiver HTTP adapter makes use of the variables defined in the iflow &username=${header.username}&password=${property.password} for configuring the target query.

The response of this call returns a JSON containing  “access_token”, “refresh_token” and “expires_in”.
Further this subflow calls another subflow to Write/store the above message to the data store and call Hybris Products Search REST api to get products.
Subflow 1a: To store message in data store and call products search api in Hybris.
Content Modifier is used to introduce a root element, so that the above JSON could be converted to XML using JSON to XML converter.

1a:Message Mapping Since the response JSON returns the “expires_in” value in seconds from the current time when the initial access token was requested. we use message mapping to capture the  current date into an element called “expiry_date”  ( <xs:element name=“expiry_date” type=“xs:dateTime”/> ) in format yyyy/MM/dd

1a:Data Store Write Operation is used to write the converted response XML message containing the  tokens and the expiry_date, to data store username with the value of entry ID  ${header.username} i.e. test1@hybris.com

using an XPath expression the access_token is written to the content modifier property which is later used in the script to put in the HTTP header.

1a: Script to add authorization token:Eventually the following script clears the content of the body and sets the HTTP header key  as “Authorization” and HTTP header value as “Bearer a62sbf19-c72d-47zz-935a-1c975cd24642

importClass(com.sap.gateway.ip.core.customdev.util.Message);
importClass(java.util.HashMap);
function processData(message) {
	//body
	var body = message.getBody();
	message.setBody("");	
	//properties
	map = message.getProperties();
	var access_token = map.get("access_token");
	message.setHeader("Authorization", "Bearer "+access_token.toString());
	return message;
}

1a: Call Product Search REST API :  using http sender adapter with “get” operation, REST product search api on Hybris is called to get products based on the dynamic User Group “${header.UserGroup}” in the URL.

So far we achieved the following in PART-1:
We make an initial call from API to HCI to fetch products. Since this is the first ever request our MainFlow in HCI receives, the data store “code_hashmap”  would not exist. An exception in HCI would  then trigger exception subprocess which in turn triggers the subflow to request Initial OAuth Tokens  and subflow  to store message/tokens in data store.
In the next part here, I’ll share how we could check the validity of the obtained token and request a new token if the validity of the token is expired.

Last but not the least. I would like to thank Roy Sanders for helping me understand various authentication protocols and inspiring me to write this blog.

Part-2: https://blogs.sap.com/2016/12/28/hci-hcp-is-oauth-deciphered-retrieving-access-tokens-dynamically-part-2/

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Mark Bernabe

    Hi Amber,

    I have a similar scenario that uses Get Data Store operation. If there’s no match/result for the Entry ID, there’s an Exception. So I also have an Exception SubProcess to handle that and to proceed with my the process. Finally, in the end I’m getting my desired result but in the Message Monitoring, the status is FAILED. Perhaps because of the exception? Did you also experience the same?

    (0) 

Leave a Reply