Amber Badam
Read all my blogsHow to consume an On-Premise REST service via SAP API Management and SAP HCI (HCP-IS) using JWT for authorization and authentication
Mobile/Desktop App
Upon registering a device/user with our services we generate a token for the device/user.
The App passes the JWT token in the HTTP Header as “Authorization” to the API proxy.
SAP API Management
Create an API proxy which is coupled with a service on HCI. As we know an API is exposed in SAP API Management as an API Proxy which further decouples an API from any backend changes.Go to SAP API Management API portal and click on Develop as shown in screen print below.
Later in this blog, we will configure an iFlow on HCI which has sender channel as HTTP. Since it will be an HTTP adapter on HCI system the endpoint of the HCI iFlow would be https://<host>:<port>/http/<path>
Use this HCI URL in the following screen. In the API Base Path field, provide a path prefix for the API. for example, /api
Flow
Select the PreFlow and assign the following policies:
Extract Variable Policy:
<!-- Extract content from the request or response messages, including headers, URI paths, JSON/XML payloads, form parameters, and query parameters -->
<ExtractVariables async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
<Header name="Authorization">
<Pattern ignoreCase="true">{jwt}</Pattern>
</Header>
<Variable name="jwt"/>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
Assign Message Policy:
<!-- This policy can be used to create or modify the standard HTTP request and response messages -->
<AssignMessage async="false" continueOnError="true" enabled="true" xmlns='http://www.sap.com/apimgmt'>
<Remove>
<Headers>
<Header name="Authorization"></Header>
</Headers>
</Remove>
<Add>
<Headers>
<Header name="JWT-Authorization">{jwt}</Header>
</Headers>
</Add>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<AssignTo createNew="false" type="request">request</AssignTo>
</AssignMessage>
Assign Message Policy:
<!-- This policy can be used to create or modify the standard HTTP request and response messages -->
<AssignMessage async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
<AssignVariable>
<Name>basicAuth.username</Name>
<Value>s000000000</Value>
</AssignVariable>
<AssignVariable>
<Name>basicAuth.password</Name>
<Value>ACOREL</Value>
</AssignVariable>
<!-- Sets a new value to the existing parameter -->
<Set>
<Payload contentType="application/json" variablePrefix="@" variableSuffix="#">{"name":"foo", "type":"@apiproxy.name#"}</Payload>
</Set>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<AssignTo createNew="false" type="request">request</AssignTo>
</AssignMessage>
Basic Authentication Policy:
<BasicAuthentication async='true' continueOnError='false' enabled='true' xmlns='http://www.sap.com/apimgmt'>
<!-- Operation can be Encode or Decode -->
<Operation>Encode</Operation>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<!-- for Encode, User element can be used to dynamically populate the user value -->
<User ref='basicAuth.username'></User>
<!-- for Encode, Password element can be used to dynamically populate the password value -->
<Password ref='basicAuth.password'></Password>
<!-- Source is used to retrieve the encoded value of username and password. This should not be used if the operation is Encode-->
<Source>request.header.Authorization</Source>
<!-- Assign to is used to assign the encoded value of username and password to a variable. This should not be used if the operation is Decode -->
<AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>
Request Cache:
<ResponseCache async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
<CacheKey>
<Prefix/>
<KeyFragment ref="request.uri" type="string"/>
</CacheKey>
<ExpirySettings>
<TimeoutInSec>300</TimeoutInSec>
</ExpirySettings>
<SkipCacheLookup>request.header.InvalidateCache="true"</SkipCacheLookup>
<SkipCachePopulation/>
</ResponseCache>
TargetEndpoint Flow:
JavaScript Policy:
Add script file listparameters.js in the Scripts section and reference this file in the policy below. Following script adds the following “&fields=products(name,code)” to query string when the Request does not contain them.
var Turl = context.getVariable("target.url");
var Ruri = context.getVariable("request.uri");
var Rpath = context.getVariable("request.path");
var qs = context.getVariable("request.querystring");
if( qs.indexOf("fields") <= -1 ){
context.setVariable("target.url", Turl+Rpath.slice(5)+"?"+context.getVariable('request.querystring')+"&fields=products(name,code)")
}
SAP HCI
Create an Iflow with Sender Channel with adapter type as HTTPS and transport protocol HTTPS.
Adjust the address of the sender channel as “/products/search”.
Define the receiver channel with adapter type as HTTP as follows.
Enter the header name “JWT-Authorization” in HCI runtime configuration . This enables to retain the header value from the incoming message from API.
Using Script message transformer in HCI iFlow, convert the Header value “JWT-Authoriation” to “Authorization” by assigning the following JS.
importClass(com.sap.gateway.ip.core.customdev.util.Message);
importClass(java.util.HashMap);
function processData(message) {
//headers
var map = message.getHeaders();
var jwt = map.get("JWT-Authorization");
message.setHeader("Authorization", jwt);
message.setHeader("JWT-Authorization", null);
return message;
}
Testing the API
To test the API using API Test console , choose the API proxy and provide the header key “JWT-Authorization” and its corresponding token value and hit send to see the results.
Debugging the API
We can activate debugging on API from either the Development or the test console.
Go to API development page and select the API proxy tab and display the API you want to debug. Click on debug api and eventually on “Start Debugging”.
Call your service and click on refresh button to display details of the each step processed in various flows. More samples on SAP API management on GitHub here.