Skip to Content
Technical Articles
Author's profile photo Víctor Jiménez Osorio

Dynamic Authentication in UDF Mapping to Use Token in REST Receiver Channel

Hello,

As a Software Engineer I needed to create an interface between an SAP System and a third party API using XML as request and response but calling the API through REST adapter. After reading some blogs about creating a Lookup service within a UDF and how to use the REST adapter I have developed this implementation.

Requirement

I need to call an API which a dynamic token given by the same service must be included in the header parameters.

Request and Response must be XML format.

Using the API itself

Getting the Token

Request:

Method: POST
Endpoint: https://<hostname>
Resource: /api/v1.3/auth/token
Parameters: ?user_name=<user_name>&password=<password>&auth_type=password
Body: None

Response:

{
"authToken": "<authToken>",
"issuedAt": <issuedAt>,
"endPoint": "<endPoint>"
}

Using the Token in a second request

In these example I’m retreiving my account information

Method: GET
Endpoint: https://<hostname>
Resource: /api/v1.3/user/info
Parameters: None
Body: None

Headers:
Authorization: <authToken> //retrieved in previous request

Response:

{
    "accountName": "<accountName>",
    "userName": "<userName>",
    "userEmail": "<userEmail>"
}

Implementation in SAP PI

ESR Objects

I used the UDF within the request Message Mapping. Since there is no body, I just needed the Token as an input:

The response Message Mapping is all one to one element

Code for the UDF

The inputs are the communication component and communication channel names. I’m using global variables in the UDF since I’m using it in many interfaces but you can set these values by parameters from the configuration side.

//Imports:
javax.xml.parsers.*;
org.w3c.dom.*;

public String getToken(String commComp, String commChann, Container container) throws StreamTransformationException{
Channel channel= LookupService.getChannel(commComp,commChann);
SystemAccessor accessor = LookupService. getSystemAccessor(channel);
StringBuffer sb = new StringBuffer();
String token = "";
try{		
		InputStream inputStream;
		String reqString ="."; //This is to avoid XMLPayload is empty Exception
		inputStream = (InputStream) new ByteArrayInputStream(reqString.getBytes());
		Payload payload = LookupService.getXmlPayload(inputStream);
		Payload RESTOutPayload = accessor.call(payload);
		InputStream inpStr = RESTOutPayload.getContent();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(inpStr);
		NodeList list = document.getElementsByTagName("authToken");
		Node node = list.item(0);
		if(node !=null) {
			node = node.getFirstChild();
			if (node !=null) {
				token = node.getNodeValue();
			}
	}
}
catch (Exception e){
	e.printStackTrace();
}
finally {
	if (accessor!=null) accessor.close();
}
return token;
}

ID Objects

Receiver Channel used in the UDF

You can also send the user and password from de Message Mapping but I rather to set this data in the configuration side:

Request and Response format must be JSON since it’s the format used by the API. I’m converting the response to XML so I can get the value by tag name in the UDF:

For this scenario I’m using XML as request and response but you can use JSON either on request or response.

Sender Channel

Since this is a synchronous scenario I just need to set the QoS to Best Effort

Receiver Channel

I get the dynamic token value from the target of the request Message Mapping

Request and Response must be JSON format since it’s the format used by the API. I’m converting from and to XML in both request and response since that’s my scenario. You can use same JSON either on request or response depending on your scenario.

I need to wrap the response to the MT used in the response Message Mapping.

The Token value is included in Headers tab

That’s it, now the dynamic token is included in the header of the request and I’m able to retrieve the information in a single request from PI:

I hope this blog is helpful for you.

Feel free to share any feedback or thoughts.

Reference Blog posts:

REST Look Up using UDF in SAP PO | SAP Blogs

OAuth 2.0 authentication within a UDF mapping to be included in REST receiver channel | SAP Blogs

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Anurag Gupta
      Anurag Gupta

      How did you make the token cacheable so that you don't call it for every request?

      Author's profile photo Víctor Jiménez Osorio
      Víctor Jiménez Osorio
      Blog Post Author

      Hello,

      We need to get the token in every request.

      Author's profile photo Sven Kelemen
      Sven Kelemen

      Hi, this works, thanks. My API responds with a token in the response header, not in the payload. I can see it in XPI_inspector trace of "commChann". I tried using DynamicConfiguration without success. How to get it in getToken UDF?

      Author's profile photo Chaitanya Gandepalli
      Chaitanya Gandepalli

      Hi There,

      can we send basic authentication dynamically ?

      Regards,

      Chaitanya.