SAP CPI With BTP
SAP CPI With BTP
PART 1 - How to generate & verify RS256 PKCS8 JWT token within SAP CPI
iFlow (using BTP trial account)
• Notes: In this blog post I will do step by step walk through for generating JWT token within the
iFlow using groovy script
• Assumptions:
o You have a BTP account and you have created a integration suite instance
o You have basic knowledge of creating iFlow and necessary controls within
1. Step 0: Get Client Id and Client Secret for Integration flow
1.1. The client id and client secret are used in creating authorization named below as ‘btpauth’
1.2. Go to your BTP trial account and select Instances & subscriptions
1.3. Scroll to Instances and Click the “1 Key” link. Make sure you select the link from “Integration
Flow” line
1.4. You will see the JSON along with the credentials. Copy the JSON and save it. Use the values of
client id and client secret from this JSON
1.5. You will use these values in the Integration Suite for creating Authorization to be used for calling
from postman
1.6. You will also use these values to create a User Credential variable in Monitor – Manage Security
Material, as described in the below step
2. Step 0: Get Client Id and Client Secret for API (NOT USED)
2.1. Go to your BTP trial account and select Instances & subscriptions
2.2. Scroll to Instances and Click the “1 Key” link. Make sure you select the link from “api” line
2.3. You will see the JSON along with the credentials. Copy the JSON and save it. Use the values of
client id and client secret from this JSON
3. Step 0: Create User Credentials
3.1. Go to Monitor -> Manage Security Material
3.2. Select Create -> User Credentials
7.4. This will open a box where you can select signing response file to be uploaded
7.5. The following signing response formats are supported:
7.5.1. PKCS#7 in binary or PEM or base64 textual encoding (*.p7c)
7.5.2. Chain of DER-PEM encoded X.509 certificates in one file (*.*)
7.5.3. X.509 PKI path (sequence of certificates with top CA certificate at index 0) (*.pkipath)
7.5.4. Software Publisher Certificate (SPC) (*.spc)
7.6. In the popup select “*” to see all files from the folder where you have kept downloaded
certificates
7.7. Select the ‘.cer’ file. For reference, the first file you downloaded that said “your signed
certificate”
7.10. Click Confirm to confirm the signing response and return back to Manage Keystore page
7.11. Note: Currently, the upload size limit for signing responses is at 30720 bytes.
8. Step 5: Creation of iFlow
8.1. Select “Design – Integration & API” from Integration Suite
8.2. Choose Create to create a new Package
8.5. This will open the Add Integration Flow window where you provide the mandatory information
8.6. Click OK to create the iFlow
8.7. Now Click on the iFlow artifact to see empty iFlow, where you click Edit to edit the iFlow
8.8. Link the sender with HTTPS and provide following details. Make sure you have un-checked the
CSRF Protected. You can given any address here, this is the final name of API that your caller will
call
8.9. Now add a Content Modifier and add following Exchange properties. You can add any properties
you want. Remember this is what you will need to send in the Body as XML when you call this
iFlow
8.10. Now add a Groovy Script control to add the script which will generate the JWT and
return as response. Click the “Create” from the list
8.11. This open the editor where you can overwrite the content with the groovy script given
below and click OK
groovy_blog_generat
eJWT.txt
TO Decode use:
8.12. Add Content Modifier to receive the token in the MessageBody. This token is what we
generated in the script and which I have added as property to be returned in the script using
message.setProperty("token", jwtToken);
8.16. Click the Deployment Status tab to see the deployment details
8.17. Click the Navigate to Manage Integration Content to find the exact URL using which you
can call the iFlow
8.19. THAT’s IT
9. Test JWT Generation using Postman
9.1. Open Postman and create a new request
9.2. In Authorization, select Basic Authorization and provide clientid in UserName and clientsecret in
Password. These are the values you got in Step 1.
9.3. Provide body as follows. Remember that we used these fields in the first Content Modifier as
XPath. You can provide this as per your requirements. Make sure you reflect the change in
groovy script as well. And click Send and wait for the response
10. Verify the JWT received
10.1. We will simulate this by creating 2 iFlows. First iFlow “bankNEFT” will receive the
payload from myLab iflow. It will then call the another iFlow, “validateJWT”, which will validate
the JWT based on the keypairname and return either true or false in the body depending on
verification results
10.2. In the “validateJWT” iFlow
10.2.1. we will use global Write variables to store the value of verification result
10.2.2. we will also use Data Store Write operation to store these values in the CPI datastore to
be accessed by “bankNEFT” iFlow. Make sure you have checked the “overwrite existing
message” box. We will not give any id. The name given in the Data Store name is used in
the bankNEFT iflow as well
10.3. In the “bankNEFT” iFlow
10.3.1. We will use data store select operation, give the same data store Name as given in the
“validateJWT”. Make sure you have checked “Delete on Completion” check box
<root>
<keypairname>blog_rsa_key</keypairname>
<payload>
"type": "account",
"remitterMobileNumber": "9113054668",
"transactionId": "5297",
"beneficiaryMobileNumber": "9448244804",
"beneficiaryAccNo": "1452500100093401",
"beneficiaryEmailId": "[email protected]",
"remitterAddress": "M S Building, Bangalore",
"purpose": "P08",
"countryCode": "IND",
"transactionAmount": "17553247.00",
"remitterEmailId": "[email protected]",
"remitterAccNo": "520143000000025",
"beneficiaryBankIFSCCode": "KARB0000145",
"transactionDate": "17032023",
"serviceName": "encFundTransferService",
"entryNo": "1238404",
</payload>
<token>eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjIwMDAifQ.eyJleHAiOjE3MDA4Mz
YzMTUsInVzZXJpZCI6InZpbmF5YmhpZGUiLCJwd2QiOiIxMjM0In0.mE4cJOdiHdWBM3X-MV-
lxM7sXIsaYsaCSZ0kQ7kVKVHsxHBgQIFyUbtR1VKOrlL-gv-
u8rX77n_aVbOLb35L3vtUzn3ZeKu26nz5SmPoTG6jq4MzUc2RILHfOJCMRpQqgAD-
pgOKbmef7NmZAB7MEgA8JWF7aM_EHOv3EkEf3RfmQMkoWR6HT6KO5ZFoExjq5Qi2GyaA
aEgNDKvJmy42SuxDdQRnZxCfgASB1IGg7PV0ZOgQJUId9R_rxcmjsIDQH9QAJRFHblpII3he1ty
P5_HBbz0ZL_SERIZYUjcXoiXz4o5SO7cNXhBy6RHdWqUVnIoLfmyDNY8CEP3P6JgznQ</token
>
</root>
11.1.3. Create a content modifier and add two exchange properties as shown below
11.1.4. Add groovy script where we will do the verification. IMPORTANT: The message body has
to be in XML format, else the caller Select Data Store operation will FAIL
groovy_validateJWT.t
xt
11.1.5. This groovy script adds a property “verificationResult” where the signature verification
status is saved
11.1.6. Create a Write variable control, and make sure you have checked the Global scope
check box
11.1.7. Now add a data store operation - Write control. This is used to save the
verificationResult in the data store as well as body of the current iFlow. Which can be
accessed by any other iflow. Make sure you have checked the overwrite existing message
check box to test this iflow repeatedly. If you do not do this then you have to delete this
from the overview console after each time you execute this iFlow
<root>
<keypairname>blog_rsa_key</keypairname>
<payload>
"type": "account",
"remitterMobileNumber": "9113054668",
"transactionId": "5297",
"beneficiaryMobileNumber": "9448244804",
"beneficiaryAccNo": "1452500100093401",
"beneficiaryEmailId": "[email protected]",
"remitterAddress": "M S Building, Bangalore",
"purpose": "P08",
"countryCode": "IND",
"transactionAmount": "17553247.00",
"remitterEmailId": "[email protected]",
"remitterAccNo": "520143000000025",
"beneficiaryBankIFSCCode": "KARB0000145",
"transactionDate": "17032023",
"serviceName": "encFundTransferService",
"entryNo": "1238404",
</payload>
<token>eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjIwMDAifQ.eyJleHAiOjE3MDA4Mz
YzMTUsInVzZXJpZCI6InZpbmF5YmhpZGUiLCJwd2QiOiIxMjM0In0.mE4cJOdiHdWBM3X-MV-
lxM7sXIsaYsaCSZ0kQ7kVKVHsxHBgQIFyUbtR1VKOrlL-gv-
u8rX77n_aVbOLb35L3vtUzn3ZeKu26nz5SmPoTG6jq4MzUc2RILHfOJCMRpQqgAD-
pgOKbmef7NmZAB7MEgA8JWF7aM_EHOv3EkEf3RfmQMkoWR6HT6KO5ZFoExjq5Qi2GyaA
aEgNDKvJmy42SuxDdQRnZxCfgASB1IGg7PV0ZOgQJUId9R_rxcmjsIDQH9QAJRFHblpII3he1ty
P5_HBbz0ZL_SERIZYUjcXoiXz4o5SO7cNXhBy6RHdWqUVnIoLfmyDNY8CEP3P6JgznQ</token
>
</root>
12.2. Create HTTPS connection to Start
12.6. Now add a Data Store Operation for Select, with same name as given in validateJWT
12.7. Now add a content modifier where you will save the global variable set in validateJWT in
a local property and also save body received from validateJWT
12.8. Add a groovy script, where you can save the payload property in the body or simulate
the bank logic
groovy_bankNEFT.txt
13.3. Once you execute the bankNEFT API, internally it will pass the above body to
validateJWT iFlow and returns true or false in the body depending on JWT verification result