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.
Eng Swee Yeoh 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/
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?
Hi Mark,
Thats true. Once the exception is caught, HCI registers it as a failed flow. more info here
Hi Amber, if we are using the REST API from Android mobile --> how do we safely store the refresh token. Like, if an attacker gets access to refresh token he can keep on generating new access tokens and use the API.
I am assuming password grant type in Oauth2 with only username and password.
Hi Amber,
First, thank you for this blog as it has been very helpful. I'm hoping that you can help me find a solution to a issue that I'm encountering. I am needing to perform a token request in JSON format. Currently, I am using a Content Modifier to hard code the client_id and client_secret into the XML body and then I am using the XML to JSON Converter. My current road block is that our client secret contains the some characters <n/ and the remaining characters of the password. The XML to JSON Converter is giving me the error (of course) Error = javax.xml.stream.XMLStreamException: ParseError at [row,col]:[4,26]
Message: Element type "n" must be followed by either attribute specifications, ">" or "/>".
Any idea how to get around this other than requesting a new password and ensuring that it doesn't contain any < or >?
Thank you!!!
THank you AMber,
I have a scenario wherein I have to send some data from R/3 through HCI to a web service. The authentication is done through OAUTH 2.0. Since the initiation of the process is from R/3 how best can the scenario be supported from HCI.
Kind regards,
Anand S