Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
Showing results for 
Search instead for 
Did you mean: 
Active Contributor
In Part-1 of this blog we saw

  • How to setup trust between SAP CPI and Salesforce and

  • Implement Main Flow to consume Salesforce API.

In this blog let us see how to implement Integration flow to fetch access token using JWT Bearer Flow and update global variable.

Before we move into Integration Flow configuration lets us also understand the details of JWT Bearer implementation of Salesforce. 

Salesforce - Create JWT Bearer Token

  • Construct a JWT header with this format: {"alg":"RS256"}and encode it using Base64url

  • Construct a JSON Claims Set for the JWT with isssubaud, and exp and encode it using Base64url

{"iss": "<Client_ID>", 
"sub": "<>",
"aud": "",
"exp": <expiration time of the assertion within 3 minutes>}

  • Create a string with format: encoded_JWT_Header + "." + encoded_JWT_Claims_Set

  • Sign the resulting string using SHA256 with RSA.

  • Create a string with format encoded_JWT_Header + "." + encoded_JWT_Claims_Set + "." + base64_encoded_signature 

Salesforce - Fetch Access token

Post the JWT Bearer Token constructed to with below parameters

  • grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer

  • assertion=JWT bearer token

After the request is verified, Salesforce responds with access token, instance URL etc.

Integration Flow Design

Now let us design Integration flow to construct JWT token that comply with format rules specified in RFC7519 and post it to Salesforce token endpoint. The iflow also implement logic to parse JSON response, retrieve and store access token and instance URL in global variables.

Limitations with standard Step Type

  • Base64 Encoder: Output text is not URL safe.

  • Simple Signer : The signature value computed is Base64 encoded and hence not URL safe.


To overcome the limitation I have implemented Script to

  • Perfrom Base64url encoding using org.apache.commons.codec.binary.Base64 library 

  • Replace characters + and / with - and _ respectively and remove = from signature to make it URL safe.

SAP should probably consider including URL safe encoding feature in CPI roadmap.

Step Type Name Description

Content Modifier


Set Message Body to {"alg":"RS256"}

Script b64URL1 Base64 URL Encode JWT header



  • Read SFDC client ID stored in Secure store and set it in property field "clientID"

  • Compute epoch timestamp and set in property field "expTime"

Content Modifier setClaimSet

  • Store encoded JWT header to exchange property "jwtheader"

  • Populate message body with JWT claimset

Script b64URL2 Base64 URL Encode the JWT claimset
Content Modifier constructToken

Append JWT Header and JWT Claimset with .(dot) delimiter

Note: All steps until here (6 totally) can be combined in to one using Groovy Script. For demonstration I have used standard step types.



  • Sign the message body with Private key created with alias "sfdctoken" (Part-1) using RSA SHA256 algorithm.

  • Store resulting signature in "JWTSignatureValue" header.

Script b64URL3 Make the Signature value in header URL safe using string replace operation.
Content Modifier appendSignature

  • Insert Content-type = application/x-www-form-urlencoded header and

  • Populate Body with the grant_type and JWT assertion

Content Modifier DeleteHeader

Remove all headers except content-type.

Request Reply callAuthServer

Invoke Salesforce token endpoint.

Upon successful JWT validation salesforce return bearer access token.

"access_token": "00Dxx00001gPL.39u",
"scope": "web openid api id",
"instance_url": "",
"id": "",
"token_type": "Bearer"
Script extractToken Parse JSON Response and extract access token and instance URL
Write Variable saveToken

Save access token, instance URL and timestamp in global variable


Base64url Encoding Script
import java.util.HashMap;
import org.apache.commons.codec.binary.Base64;

def Message processData(Message message) {

def body = message.getBody();

return message;

Set Required Property Script
import java.util.Date;

def Message processData(Message message) {

//Set expiry time property value
Date d = new Date();
message.setProperty("expTime",((d.getTime() / 1000) + 180).intValue());

//Read SFDC connected APP client ID
def service = ITApiFactory.getApi(SecureStoreService.class, null);
def credential = service.getUserCredential("SFDCClientCred");
String clientID = credential.getUsername();
//Store client ID as property
message.setProperty("clientID", clientID);

return message;

Make Signature URL Safe Script
import java.util.HashMap;

def Message processData(Message message) {

//Get Signature value from header
map = message.getHeaders();
signedContent = map.get("JWTSignatureValue");

//Replace characters to make it URL safe
signedContent = signedContent.replaceAll("\n","").replaceAll("\\+","-").replaceAll("/", "_").replaceAll("\\=","");

//Set URL safe Signature in header
message.setHeader("JWTSignatureValue", signedContent);

return message;


Parse JSON Response and read values
import java.util.HashMap;
import groovy.json.*
def Message processData(Message message) {

//Get Response Payload
def body = message.getBody(String.class);

//Parse JSON Payload
def jsonSlurper = new JsonSlurper()
def list = jsonSlurper.parseText(body)

//Retrieve required values and store it in property

return message;



Below is the screenshot from SAP CPI Trace

Main Flow - Request : Session Validity calculated false and Token Flow invoked

Token Flow - Fetch Token HTTP Request : Header & Payload

Token Flow - Fetch Token HTTP Response : Payload

Main Flow - HTTP API Request : Header

Main Flow - HTTP API Response : Payload

Labels in this area