Skip to Content

SAP Gateway allows to easily expose services of a SAP backend system: Those services then can be consumed by “modern” types of web applications. For a demo case, I had the requirement of bringing in some new data from a web application into a SAP backend system for further processing.

I implemented that via a Node-RED flow: Node-RED is a programming tool for wiring together devices, APIs and online services in a graphical manner. Such a “flow” is built in via a browser-based editor and then can be deployed to the Node-RED runtime running either on-premise or in the cloud.

In this blog, I’ll show how to handle “Create” (HTTP POST) operations via SAP Gateway for such a Node-RED flow: It took me some iterations to get this running – so I thought it is worth to share this experiences… (I don’t focus on service creation here – and assume that the “Create” service is already defined in the SAP Gateway)

Prerequisites: SAP Gateway knowledge, and a rudimentary knowledge of Node-RED, Javascript and http requests.

Background

SAP Blog “Gateway protection against Cross-Site Request Forgery attacks” explains in detail the protection mechanisms of SAP Gateway against Cross-Site Request Forgery (CSRF): A client application, which likes to invoke a transaction via a modifying request (HTTP POST, PUT or DELETE) via an SAP Gateway REST service, needs to authenticate first and the request needs to be signed with a CSRF-Token as a secret key. The CSRF token is only known by the client application context and the SAP Gateway.

To request the CSRF-Token the client application issues a GET request with header variable X-CSRF-Token set to value ‘fetch’ to the SAP Gateway service first – the SAP Gateway service then generates a new random token and returns the value in the response (via header variable and cookie). The client application reads the CSRF Token from the HTTP GET Response, and includes the value as header parameter X-CSRF-Token for the modifying (HTTP POST, PUT DELETE) request to the SAP Gateway. As the token value is also part of the response via cookie, the cookie needs to be included in the modifying request.
(The SAP Internet Communication Framework (ICF) runtime on the SAP Gateway system checks for the X-CSRF-Token in both request header and cookie – the token needs to be present in both, and the values need to be equal – only then the transaction is executed via the SAP Gateway).

Modelling in a Node-RED flow

The flow below is an example for handling the x-crsf-token and session cookie to avoid HTTP error 403 (Forbidden) in the POST request within Node-RED. The example flow is manually triggered, the X-CSRF-Token fetch request is added to the http header, an first GET request to the SAP Gateway fetches the token, then both token and cookie are added to the (new) header, post data for the transaction is added to the payload, and then the POST call gets issued.

Here a detailed view on the respective nodes of the flow:

Function Node to prepare the GET request

The function node has the appropriate JavaScript code for the token request in the header:

// Request CSRF token with fetch
msg.headers = {};
msg.headers["accept"] = "application/json";
msg.headers["x-csrf-token"] = 'fetch';
return msg;

HTTP Request Node (GET to SAP Gateway)

The HTTP header is submitted via GET to the SAP Gateway service:

As a result, SAP Gateway returns the CSRF token and the session cookie – those are extracted in the next node.

Function Node to prepare the POST request

CSRF and cookie of the response are extracted and added to the header for the next request. pData contains the object which is sent via POST to the SAP Gateway service – this needs to correspond to the data format expected in the service description:

var token = msg.headers["x-csrf-token"];
var cookie = msg.headers["set-cookie"];
// msg.header
msg.headers = {};
msg.headers["cookie"] = cookie;
msg.headers["x-csrf-token"] = token;
msg.headers["content-type"] = 'application/json';
msg.headers["charset"] = 'utf8';
// msg.payload = "data to post"
var pData = {"d":{"Barcode":"00000098","Name":"TEST ENTRY 98"}};
msg.payload = pData; 
return msg;

HTTP Request Node (POST to SAP Gateway)

Final POST submitting the header and the transaction data to the SAP Gateway service

Sample flow to import into Node-RED

Import the flow and modify << SAP Gateway Service URI >>,
add user credentials, and modify the pData array corresponding to your SAP Gateway service accordingly:

[{"id":"f4ece51b.898f1","type":"tab","label":"SAP Gateway POST"},{"id":"27c09c2b.fce3bc","type":"debug","z":"f4ece51b.898f1","name":"Result final","active":true,"console":"false","complete":"true","x":1059.9722900390625,"y":258.4444580078125,"wires":[]},{"id":"86d117c4.bdb0b8","type":"http request","z":"f4ece51b.898f1","name":"Call POST to SAP Gateway","method":"POST","ret":"txt","url":"<< SAP Gateway Service URI >>","tls":"","x":827.083251953125,"y":258.5833435058594,"wires":[["27c09c2b.fce3bc"]]},{"id":"476828e7.c82c3","type":"function","z":"f4ece51b.898f1","name":"Set token and cookie in msg.headers","func":"var token = msg.headers[\"x-csrf-token\"];\nvar cookie = msg.headers[\"set-cookie\"];\n// msg.header\nmsg.headers = {};\nmsg.headers[\"cookie\"] = cookie;\nmsg.headers[\"x-csrf-token\"] = token;\nmsg.headers[\"content-type\"] = 'application/json';\nmsg.headers[\"charset\"] = 'utf8';\n// msg.payload = \"data to post\"\nvar pData = {\"d\":{\"Barcode\":\"00000098\",\"Name\":\"TEST ENTRY 98\"}};\nmsg.payload = pData; \nreturn msg;","outputs":1,"noerr":0,"x":499.0001220703125,"y":260.08349609375,"wires":[["86d117c4.bdb0b8"]]},{"id":"ef80a5c6.d40b18","type":"http request","z":"f4ece51b.898f1","name":"Call GET to SAP Gateway","method":"GET","ret":"obj","url":"<< SAP Gateway Service URI >>","tls":"","x":670.0833129882812,"y":105.58336639404297,"wires":[["476828e7.c82c3"]]},{"id":"1593bfe0.85f49","type":"function","z":"f4ece51b.898f1","name":"Set header to request CSRF token","func":"// Request CSRF token with fetch\nmsg.headers = {};\nmsg.headers[\"accept\"] = \"application/json\";\nmsg.headers[\"x-csrf-token\"] = 'fetch';\nreturn msg;","outputs":1,"noerr":0,"x":369.5,"y":105.49999237060547,"wires":[["ef80a5c6.d40b18"]]},{"id":"38e1cb45.423aac","type":"inject","z":"f4ece51b.898f1","name":"Trigger Flow","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":137.4444580078125,"y":42.72221374511719,"wires":[["1593bfe0.85f49"]]}]

 

So I hope this will help you connecting your Node-RED flows to SAP Gateway –
I will attempt to share my further experiences in further posts ;-

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply