Logic apps and CSRF token validation failed
Tumbled up in a situation where I had to manipulate data in SAP C4C through Odata API. I started playing with the api with Postman and VSCode Rest Client and all looked good. I was able to fetch and update data. Following the developer guide I fetched the CSRF Token which is needed to update/insert/delete data and used it in Http PATCH call.
The disappointment
But when trying to update data with Azure Logic App, the update http call response was “CSRF token validation failed”. What was the Logic App doing different as opposed to Postman and VSCode?
Solution?
I googled up a bit and found a SAP blog describing same kind of situation with SAP S/4 Hana. From the blog I found out that there is cookies in play. Apparently Postman and VSCode Rest Client handled session cookies automatically behind the scenes, but Logic App obviously didn’t.
I passed cookies (that I got from previous GET request’s response) to my “patch” http connector. No cigar, the response was again “CSRF token validation failed”.
Meet the working solution
Frustrated I continued googling and nothing useful seem to come up, only advise on passing cookies to requests. Then in one forum post mentioned that maybe just SAP session cookie is needed, not all the cookies. So I looked up the cookie string and there was more than one cookie and the second cookie in the string appeared to be the SAP session cookie (starting something like SAP_SESSIONID…).
I came up with a quick and dirty logic app expression to pass only the SAP session cookie to patch request. Like this:
split(outputs('HTTP-GetOpportunity')['headers']['Set-Cookie'],',')[1]
And lo and behold, it worked!
But anyway, I think that the API documentation could be better. It took me some time and effort to figure out how to solve the problem. Though it could be also that I’m not so familiar with SAP and it’s “quirks”.
Bonus tip
One bonus tip for you if you’re using SAP api’s and liquid transforms with logic apps. When transforming payloads to SAP api requests with liquid, the datetime values are troublesome. For example when passing “2021-12-04T00:00:00” through liquid, it transforms to “2021-12-03T23:00:00Z” (depending on the timezone, of course). And that datetime format is not acceptable in SAP api.
The quick solution to this (if you can afford to lose seconds) is to format the liquid transform like this
"{{ content.datetimedata | Date: "yyyy-MM-ddTHH:mm" }}"
That way we can “override” liquid’s obsession on deciding the datetime format for us.