cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

[SAP BYD - HELP] CSRF token validation failed

3,042

Hi Expert,

I have a problem below when I Patch to oData.

  • The first time, I Get oData with HeaderParam. It returns status 200.
  • Then I got HeaderParam "x-csrf-token" with the value which I GET it in the result and I Patch the Odata. It returns status 403 Forbidden.
  • I got an error "CSRF token validation failed" when I Patch It, I have tested it before in Postman it was successful.
  • I have tried many times like adding Cookies and changing the method Patch,... but it's not successful.

All my code I wrote in one script file, and I call GET, PATCH Odata at the same time.
P/s: So how can I fix it? I hope my question can be slove.
Thanks and Best Regards

Accepted Solutions (0)

Answers (3)

Answers (3)

kursatbeyoglu
Explorer

Hi hoangtridung2405.

I faced same problem. Actually, there are two issues, both 'POST' and 'PATCH' method and i was able to solve for POST Method. (not PATCH Method, i m still looking for solution. You can use this code, probably you problem will be solved.

By the way, i was able to reach to solve by using 'cookies'. I hope it work.

Best Regards.

...
httpMethod = "GET";
contentType = "application/json";
httpResource = "...";
body = "";
getToken = "";

headerParamater.Clear();
headerParamaterEntry.Clear();

headerParamaterEntry.Name = "x-csrf-token";
headerParamaterEntry.Value = "fetch";
headerParamater.Add(headerParamaterEntry);

var resultGETToken = WebServiceUtilities.ExecuteRESTService(scenarioName, serviceName, httpMethod, httpResource, urlParamater, headerParamater, contentType, body);
if(resultGETToken.Code.Contains("200"))
{
var getToken = "";
var cookie : cookies;
var cookieTable : collectionof cookies;

var getHeadersParameter = resultGETToken.HeaderParameters.Where(r=>r.Name == "x-csrf-token");

if(getHeadersParameter.Count() > 0) getToken = getHeadersParameter.GetFirst().Value;
foreach(var k in resultGETToken.Cookies)
{
cookie.HTTP_Name = k.HTTP_Name;
cookie.HTTP_Value = k.HTTP_Value;
cookie.Domain_Name = k.Domain_Name;
cookie.HTTP_Path_Name = k.HTTP_Path_Name;
cookie.HTTP_Secure_Cookie = k.HTTP_Secure_Cookie;
cookie.HTTP_Expiry_Date = k.HTTP_Expiry_Date;
cookieTable.Add(cookie);
}

if(getToken.IsInitial() == false)
{
patchServNow = true;
postServNow = false;
if(postServNow == true)
{
body.Clear(); // you can write your body template
headerParamater.Clear();
headerParamaterEntry.Clear();

httpResource = "...";
httpMethod = "POST";

headerParamaterEntry.Name = "x-csrf-token";
headerParamaterEntry.Value = getToken;
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Connection";
headerParamaterEntry.Value = "keep-alive";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Content-Type";
headerParamaterEntry.Value = "application/json";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Accept";
headerParamaterEntry.Value = "*/*";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Accept-Encoding";
headerParamaterEntry.Value = "gzip, deflate, br";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name ="X-Requested-With";
headerParamaterEntry.Value = "X";
headerParamater.Add(headerParamaterEntry);

var resultPOSTMethod = WebServiceUtilities.ExecuteRESTService(scenarioName, serviceName, httpMethod, httpResource, urlParamater, headerParamater, contentType, body, cookieTable);
if(resultPOSTMethod.Code.Contains("201"))
{
}
}
}
}
kursatbeyoglu
Explorer

Hi hoangtridung2405 again.

By the way, I solved problem about PATCH Method. Variable of cookieTable is same code as above, you can use.

body.Clear();
headerParamater.Clear();
headerParamaterEntry.Clear();

httpResource = "...";
httpMethod   = "PATCH";

headerParamaterEntry.Name = "x-csrf-token";
headerParamaterEntry.Value = getToken;
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Connection";
headerParamaterEntry.Value = "keep-alive";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Content-Type";
headerParamaterEntry.Value = "application/json";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Accept";
headerParamaterEntry.Value = "*/*";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "Accept-Encoding";
headerParamaterEntry.Value = "gzip, deflate, br";
headerParamater.Add(headerParamaterEntry);

headerParamaterEntry.Name = "X-Requested-With";
headerParamaterEntry.Value = "XMLHttpRequest";
headerParamater.Add(headerParamaterEntry);

body = "{" +
		"\"UpdateTicket\": {" +
			"\"custom1"   + "\" : \"" + value1 + "\"," +
			"\"custom2"   + "\" : \"" + value2 + "\"," +
			"\"custom3"   + "\" : \"" + value3 + "\"," +
			"\"custom4"   + "\" : \"" + value4 + "\"," +
			"\"custom5"   + "\" : \"" + value5 + "\""  +
		"}" +
	"}";

var resultPATCHMethod = WebServiceUtilities.ExecuteRESTService(scenarioName, serviceName, httpMethod, httpResource, urlParamater, headerParamater, contentType, body, cookieTable);

I have followed your guide and resloved the problem,

Thanks for your help.

ixdse
Explorer
0 Likes
Can you check my issue too? (commented above)
ThiagoSarmento
Product and Topic Expert
Product and Topic Expert

Hello hoangtridung2405,

The 403 Forbidden error means that there is a cookie issue.

So after you receive and store the cookies from GET call, and send them on POST call, you would need to also set the "HTTP_Secure_Cookie" parameter with value 256 or 257

  • 256: do not perform URL encoding of the cookie value, do not set the secure attribute
  • 257: do not perform URL encoding of the cookie value, do set the secure attribute

This is required as the underlying framework performs a decoding of the cookie.
Please refer to the following SAP Note: https://launchpad.support.sap.com/#/notes/3302847

I hope this helps!

Best regards,

Thiago

ixdse
Explorer
0 Likes

From SAP:

Thank you for contacting SAP Cloud Support.

This incident has reached the Support team. We have reviewed your issue and understand that you are unable to use the SubmitForApproval Action for the EmployeeTime BO and none of the actions are available for use.

Cause :The action SubmitForApproval from EmployeeTime Business Object does not support validations in ABSL if they are created outside of an Enhancement Implementation.

Resolution :
SAP has provided a standard BADI definition which can be implemented by the partners for these types of validations. The BADI name is TIM_EMP_TIME_VALIDATION_CHECK and the corresponding enhancement spot name is ES_TIM_REC_VAL_CHK_EXT. This BADI has an interface with only one method “VALIDATE” which needs to be implemented.

This interface method has importing parameter of type TIM_EMP_TIM_VAL_CHK which in turn consists of Employee Time ROOT UUID, Action Name and Recording View type code as input parameters. These parameters will be passed from the standard SAP code to the BADI implementation whenever any action will be called on the employee’s working time confirmations.

In the BADI implementation, you need to check for the Action name that is existing on the ROOT node of the TIMX_EMPLOYEE_TIME BO (if the implemented code needs to be executed for some specific actions, in this case SUBMIT_FOR_APPROVAL) and then retrieve the ROOT and ITEM node data of TIMX_EMPLOYEE_TIME business object with the help of received Root Node UUID.

After data retrieval, the conditions need to be put to validate the entered/saved time durations. If the requirement is to raise an error message only from the ESS time sheet, then the recording view type code can be checked in the retrieved ITEM data of the BO. The error message which needs to be raised can be logged into the CHANGING parameter of the interface which in turn consists of some attributes with regards to the error message like BADI implementation name, error occurred (Yes/No), message severity, error message text etc. The SAP standard code will take care of the error handling and the error message which is received from the BADI implementation will be shown onto the UI.

For this requirement, "Enhancement Implementation" from SAP Cloud Applications Studio can be used rather than SubmitForApproval Action Validation.

I hope this serves the purpose of the incident. Please feel free to reach us if there are further questions and we are happy to help you. The incident status has been set to Solution Proposed.

 

 

 

So I checked the Enhancement Options and found:

SetEmployeeTimeItemApprover

Now need to figure out how to use this.