[SAP CPI] – WORKING WITH POLICY IN SAP API MANAGEMENT – PART 01

Happy new year 2023 everybody. The first article for year 2023, I want to share my understand about POLICY in SAP APIM (API Management).

This will apply to business scenarios. Example, API proxy connect to external REST API with token as required, this mean that you have to call to Token Provider to get access token and after that assign it into API proxy to call REST API. To resolve this requirement, we will use POLICY in APIM.

What’s Policy in SAP Management ?

Policy definition and types of policies supported by API Management.

API Management provides capabilities to define the behavior of an API by using ‘policies.’ A policy is a program that executes a specific function at runtime. They provide the flexibility to add common functionalities on an API without having to code them individually each time. Policies provide features to secure APIs, control the API traffic, and transform message formats. You can also customize the behavior of an API by adding scripts and attaching them to policies.

You can apply a policy on the request or response stream. You can also specify if it’s applicable on the proxy endpoint or target endpoint. For more information, see SAP Help

BASIC REQUIREMENT

Requirement
  • Design IFLOW with HTTP Sender Adapter
  • Build API with Endpoint of IFLOW
  • Apply Policy for Target Endpoint with hardcode information of Token Provider as Token ID, Token Secret, Token URL.
Configuration
Design, Deploy and unit test IFLOW with HTTP Sender Adapter.

NOTE

To test this IFLOW, we need to create instance process integration runtime with plan integration flow. After that create service key to get information OAUTH2 as Token ID, Token secret, Token Url.

By using this service key, we test IFLOW on POSTMAN. We will have result

Build API Proxy
Apply Policy to get token ID, token secret, token URL for authen target endpoint

Because of target endpoint is IFLOW, it need access token from service key. So, in this step we will create and appy POLICY to do this.

First, We need download POLICY TEMPLATE of Business Technology Platform Connectivity

Second, apply this policy template into API proxy

Input hardcode information from service key into flow

Unit Test on POSTMAN

Unit Test on APIM

ADVANCED REQUIREMENT

Requirement
  • Create Key Value Maps for Token ID, Token Secret, Token Url dynamic
  • Configuration Policy for Main API – Above API – connect to API access token with dynamic value
  • Create API get access Token and configuration Policy call to Token Proveider to get access token
Configuration
Create Key Value Maps

In this configure, we will create key for development and production, base on value of header teant we will get value accordingly.

Configuration Policy for Main API – Above API – connect to API access token with dynamic value

Step 1 : Get access token from API Get Access Token

First step, If no access token in cache we will run policy SERVICE-CALLOUT to get access token in API token, else, we will get access token value from cache.

To deploy this check access token in cache we will use CONDITION-STRING in policy with flow variable. For more detail VARIABLE kindly view SAP Help

In this step, we will use Policy ServiceCallOut which will call to external service(Ex: REST API), because we call to API in the same domain APIM so we will config LOCALTARGETCONNECTION.

We also create new header with name is TENANT which store value DEV/PRD to transfer to API GET TOKEN. This value will be decide which dynamic token will be involve to authentication process

In this flow, we use CONDITION-STRING lookupcache.loolupAccessToken.cacheIt. This flow only run if no value access token in cache. If access token exist in cache, this policy will be by pass

fetchAccessToken

<ServiceCallout async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
	<Request>
		<Set>
		    <Headers>
				<Header name="tenant">dev</Header>

			</Headers>
			<Verb>POST</Verb>
		</Set>
	</Request>
	<Response>sapapim.oauth.response</Response>
	<Timeout>15000</Timeout>
	<LocalTargetConnection>
   	    <Path>/4c090ff0trial/get/oauth</Path>
	</LocalTargetConnection>
</ServiceCallout>

Call to API internal get access token

Step 2 : Read access token from Lookup cache

In this step, we will use policy with named is LOOKUP-CACHE to get access token from cache which cached in previous flow.

lookupAccessToken

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LookupCache async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <CacheKey>
        <Prefix>OAUTH</Prefix>
        <KeyFragment>dev</KeyFragment>
    </CacheKey>
    <Scope>Global</Scope>
    <AssignTo>sapapim.accessToken</AssignTo>
</LookupCache>
Get access token from cache

Step 3: Set Access token into header and call IFLOW

In this step, we will access token which get from previous step into header and call IFLOW

We will use Policy Assign Message Policy to do this

setAuthHeader

<AssignMessage async="false" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'>
    <Remove>
        <Headers/>
    </Remove>
	<Set>
		<Headers>
			<Header name="Authorization">Bearer {sapapim.accessToken}</Header>
		</Headers>
	</Set>
	<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
	<AssignTo createNew="false" type="request">request</AssignTo>
</AssignMessage>

OK, update and deploy API. We will go to next step.

Create API get access Token and configuration Policy call to Token Provider to get access token

Step 1: Create API /GET/OAUTH

URL no need in this step, so no need exactly.

Step 2 : Add Policy JS at Target EndPoint for PRE-FLOW

This step, we use Policy JAVASCRIPT to set variable which get from header of MAIN API

Code javascript will receive value of header key is TENANT (DEV/PRD) and concat with subfix to create new variable. With these variables, next step will read on MAPPING KEY to get dynamic value of TOKEN PROVIDER.

setVariables.JS

var tenant = context.getVariable("request.header.tenant");

context.setVariable("authserver.ClientID", tenant.concat("_TokenID"));
context.setVariable("authserver.ClientSecret", tenant.concat("_TokenSecret"));
context.setVariable("authserver.tURL", tenant.concat("_TokenURL"));
context.setVariable("req.tenant",tenant);
code javascript for Policy setVariable.

Step 3 : Get value dynamic of Token Information from KEY MAP VALUE

In this step, we will use policy KEYVALUEMAPOPERATIONS to get info credential access token

getOAuthCreds

<KeyValueMapOperations mapIdentifier="TokenDynamic" async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
	<Get assignTo="private.authserver.clientID">
		<Key>
			<Parameter ref="authserver.ClientID"></Parameter>
		</Key>
	</Get>
	<Get assignTo="private.authserver.clientSecret">
		<Key>
			<Parameter ref="authserver.ClientSecret"></Parameter>
		</Key>
	</Get>
	<Get assignTo="private.authserver.tURL">
		<Key>
			<Parameter ref="authserver.tURL"></Parameter>
		</Key>
	</Get>
	<Scope>environment</Scope>
</KeyValueMapOperations>

Step 4 : Base64 encode the ClientID:ClientSecret

This step, we will use Policy BASIC AUTHENTICATION to encode BASE 64 of CLIENTID:CLIENTSECRET

Authorization

<BasicAuthentication async='true' continueOnError='false' enabled='true' xmlns='http://www.sap.com/apimgmt'>
	<Operation>Encode</Operation>
	<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
	<User ref='private.authserver.clientID'></User>
	<Password ref='private.authserver.clientSecret'></Password>
	<AssignTo createNew="true">sapapim.auth</AssignTo>
</BasicAuthentication>

Step 5 : Create new message and POST to SERVER with new TARGET URL

In this step, we will POLICY ASSIGN MESSAGE to create new message, new header, new content type and after that POST to new target URL.

This step we will configure in POST-FLOW of Target EndPoint

setTokenURLnCred

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <Remove>
        <Headers>
        </Headers>
    </Remove>
    <Set>
        <Headers>
            <Header name="Authorization">{sapapim.auth}</Header>
            <Header name="Content-Type">application/x-www-form-urlencoded</Header>
        </Headers>
        <FormParams>      
			<FormParam name="grant_type">client_credentials</FormParam>
		</FormParams>
    </Set>
    <AssignVariable>   
          <Name>target.url</Name>   
          <Ref>private.authserver.tURL</Ref>                              
    </AssignVariable>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" type="request">request</AssignTo>
</AssignMessage>
Create new message, new header, content type and POST to new target URL

Step 6: Read response content to get access token

In this step, we will use POLICY EXTRACTVRIABLE to get data in payload response and store them in variables.

This step is configured in POST-FLOW- OUTGOING RESPONSE of Target Endpoint

readaccesstoken

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <JSONPayload>
        <Variable name="sapapim.accessToken" type="string">
            <JSONPath>$.access_token</JSONPath>
        </Variable>
        <Variable name="sapapim.expiresIn" type="integer">
            <JSONPath>$.expires_in</JSONPath>
        </Variable>
    </JSONPayload>
    <Source>message.content</Source>
</ExtractVariables>
Get data in response and store them in variables

Step 7: Cache Access Token

In this step, we will use POLICY POPULATE CACHE to store access token

This step is configured in OUTGOINT-RESPONSE of Target Endpoint

cacheaccesstoken

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PopulateCache async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <CacheKey>
        <Prefix>OAUTH</Prefix>
        <KeyFragment ref="req.tenant"></KeyFragment>
    </CacheKey>
    <Scope>Global</Scope>
    <ExpirySettings>
        <TimeoutInSec ref="sapapim.expiresIn"></TimeoutInSec>
    </ExpirySettings>
    <Source>sapapim.accessToken</Source>
</PopulateCache>
cache access token base upon header value of key tenant(DEV/PRD)

Save and Deploy. We will test API on POSMAN

Unit Test API on POSTMAN

Unit Test API on POSTMAN with wrong path in step Service Call Out

SUMMARY

In this article, I shared How to get access token for IFLOW with POLICY in SAP API MANAGEMENT by configure dynamic value (Token ID, Token Secret, Token URL) in KEY VALUE MAP. This policy is useful in scenarios connect to REST API with authentication with OAUTH2 Bearer Token. Thanks for your reading and any advise, kindly leave your comment on this.

Thanks

JOSEPH.

3 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.