Skip to Content
Author's profile photo Former Member

Issues with CSRF token and how to solve them

Lately, I was struggling with correct handling of this token. Since I found some misleading content here in community network, I would like to share with my findings.

What is CSRF, why do we use CSRF token and how long it is valid

CSRF (Cross-site request forgery) is type of attack, when attacker tries to send malicious requests from a website that user visits to another site where the victim is authenticated. Prevention from this attack is based on keeping security token during user’s session and providing it with every modify operation (PUT, POST, DELETE). If the provided token is not correct, gateway responds with HTTP 403 (“Forbidden”) return code. [1, 2]

The validity depends on your settings and SAP_BASIS release. In my case, I found out that the validity of token is set to 30 minutes.

The validity of the CSRF token depends on the release of the ABAP component SAP_BASIS and on the activation of the security session management (which is controlled via the transaction SICF_SESSIONS on the granularity of SAP clients):

1. Release < 7.03/7.31 or the security session management is inactive: An own CSRF cookie gets generated (sap-XSRF_<SystemID>_<SAPClient>) and this CSRF token remains valid for 24 hours (86400 seconds).

2. Release >= 7.03/7.31, the validity is bound to the security session, which depends on the system parameter http/security_session_timeout value (see transaction RZ11 for details on this parameter). By default, the security session management is active in these releases.” [3]

When you do not provide fresh security token with modify request, the user can end up with 403 error message and his recent entry in some form will be most likely lost. There are different ways how the token is handled.

1st issue – You are using ODataModel for modify operations and not calling refreshSecurityToken() method before them

You should be safe anyway. ODataModel has a parameter called bTokenHandling that takes care about token handling. I did not find information when openui5 started to support this functionality, but you can check it in debugger that after creating ODataModel instance, bTokenHandling is set to true by default.

So the outcome of this finding is that you do not need to use method refreshSecurityToken() unless you turn off bTokenHandling or you want to implement some special fuctionallity when refresh fails.

2nd issue – You are using datajs library and OData.request for your modify operations

There are several blog posts in SCN using this library. You should fetch CSRF token before every modify operation, if you want to prevent your user to see HTTP 403 response.

3rd issue – You are using external REST client for testing modify operation

If you do not provide the token, you will receive 403 HTTP Forbidden response with following message “CSRF token validation failed”.

In this case, you need to first fetch CSRF token, adding header parameter X-CSRF-Token : Fetch, read its content from response parameter x-csrf-token and add it manually to header of your testing modify request.

csrf1.JPGcsrf2.JPG

4th issue – You are sending files to SAP Gateway using sap.ui.commons.FileUploader and you are getting 403 HTTP response – CSRF token validation failed

Unfortunately, there is no link between fileuploader and ODataModel, so fileuploader needs to handle token validation by itself. Same logic applies here as the previous issue. Unfortunately (again), there is no way how to set http header parameter for fileuploader, so you need to redefine it by yourself and change the logic as it is described in this post Re: FileUploader and X-CSRF-Token?.

Looking forward to your feedback, let me know if some of my assumptions are not correct.

References

[1] Cross-site request forgery – Wikipedia, the free encyclopedia

[2] https://help.sap.com/saphelp_nw74/helpdata/en/b3/5c22518bc72214e10000000a44176d/content.htm

[3] CSRF Protection – Connectivity – SAP Library

Assigned Tags

      16 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Sean Stockemer
      Sean Stockemer

      Hi Peter,

      Thanks for the blog, it helped when we were developing our front-end odata calls.

      We've got no problem with getting and maintaining our csrf token, but my question is kinda related to this topic.

      How can we 'invalidate' our token for test purposes? I'm testing the redirect @ an invalid token. I've deleted the browser cookie for my site, and I get redirected at the next page refresh because the token is no longer valid. However, I'm not entirely sure that this simulates a token expiring. The system parameter is set to the default (30 minutes) for NW7.40...and I'd like to leave it at that, but to simulate the csrf token expiring, do I really have to wait and remain inactive for an entire half hour?

      Many thanks,

      Sean

      Author's profile photo Alex Liao
      Alex Liao

      Hi Peter,

      I tried the header property x-csrf-token, however, I found a new token is generated when I do post request then the two tokens are different.

      Finally, I retrieve the cookies from GET request, and set it to POST request, it runs OK.

      For your reference.

      Author's profile photo Former Member
      Former Member

      Hi Alex,

      I am using Python to call odata service. I am retrieving cookie and  x-csrf-token from the GET request and set them to POST request as below. Still I am getting 403 error in return. Please help.

      headers = {"set-cookie": r.headers.get("set-cookie"), "X-CSRF-Token": r.headers.get("X-CSRF-Token")}
      s = requests.post(url, data=json.dumps(payload),headers=headers, auth=auth)

      Regards,

      Niroop

      Author's profile photo Abdoulaye SANGARE
      Abdoulaye SANGARE

      Hi Niroop,

      I have a same problem have you find a solution?

       

      Regards,

      Abdoulaye.

      Author's profile photo Abdoulaye SANGARE
      Abdoulaye SANGARE

      Solution

      https://archive.sap.com/discussions/thread/3475717

      Author's profile photo Fred K
      Fred K

      Hi Alex,

      How did you exactly do that?

      We are experiencing the same.

      Best Regards,

      Fred

      Author's profile photo Adrian Babalau
      Adrian Babalau

      Hi Fred,

      This is just to bring more clarity on Alex's post, in case not to late:

      I was also experiencing the same in a SAP Cloud Platform java REST client app, designed to push data to some MDG ODATA services:

      • had the "X-Requested-With" header valued "XMLHttpRequest" in the GET request
      • had the "X-CSRF-Token" header, valued  "Fetch" in the GET request
      • Received the "X-CSRF-Token" header valued to an encoded string in the 200 OK HTTP response to the GET.
      • set "X-Requested-With" and "X-CSRF-Token" headers with the values:  "XMLHttpRequest", and the received encoded string respectively in a POST/PUT request
      • sent the POST/PUT
      • got the 403 Forbidden HTTP error with the error message :CSRF token validation failed"

      As already mentioned by Alex, the reason was that, without retrieving the cookies from the GET response and set them as such into the POST/PUT request, the POST is initiating a new HTTP session at ODATA GW service end and is generating a new CSRF, which obviously is different then the one POST is containing, and also obviously, fails the validation.

      This pb only happens in REST client apps and not in REST clients like Chrome Advanced REST client or Postman + Postman interceptor, where the cookies, containing among others, the SAP_SESSIONID_XXXX_100 and MYSAPSSO2 cookies that contain session initiated by the GET request  related data, are added automatically to the request, transparently for the user formatting and sending the request.

      Therefore, to summarize, in order to overcome the 403 Forbidden error, in a REST client application , all 3 headers,  X-Requested-With, X-CSRF-Token, Cookie must be explicitly retrieved and set into the POST/PUT request. Any of the 3 missed , will still lead to 403 Forbidden: CSRF token validation failed.

      In my case, as in Alex's I missed the retrieving and setting the cookies (which by far is the most subtle error, one could make, in this use case)

      To retrieve, in Java, the cookies in the GET response and set them into the next POST/PUT, the following code snippet could be used. It relies on Spring RestTemplate and related classes to send and get HTTP requests/responses.

      • It asumes the ResponseEntity<T> responseEntity object is already populated with the GET response

      private MultiValueMap<String, String> getResponseXCSRFTokenAndSetCookieHeaders(ResponseEntity<string> responseEntity) {

      • MultiValueMap<String, String> selectedHeaders = new LinkedMultiValueMap<String, String>();
        String xCSRFTokenValue = responseEntity.getHeaders().getFirst("X-CSRF-Token");

        • if (xCSRFTokenValue == null)    throw new SAPException("NO_X_CSRF_Token_RETURNED_FOR_HEADER");
      • selectedHeaders.add("X-CSRF-Token", xCSRFTokenValue);
      • selectedHeaders.put("Cookie", responseEntity.getHeaders().get("Set-Cookie"));
      • return selectedHeaders;

      }

       

      Author's profile photo Arpita Shetty
      Arpita Shetty

      Hi Peter,

      I am facing some issues related to CSRF token.

      I have a requirement where

      1. I have to send the parameters to URL (Signer gateway : It is secured automated signing solution to get signatures easily) through HTTPS POST.

      Parameters :

      > Reference number

      > PDF form

      > SUrl (The signer gateway will send the success response to this URL (SUrl)

      > Furl (The signer gateway will send the Failed response to this URL (FUrl)

      1. The page should redirect to Signer gateway on successful posting.
      2. Sign the document in signer gateway
      3. Send signed signature including some other parameters to SAP using SUrl through  HTTPS POST.
      4. Save the signed signature in SAP level.

      Note:  Created OData service and using it as SUrl.

      I wrote some code to achieve above steps and it works fine till step 3. But While achieving 4th step that is posting response from Signer gateway (non-SAP) to SAP getting 403 forbidden  error : CSRF token validation failed.

      1. Is it possible to achieve POST method from non-SAP to SAP without passing CSRF token?
      2. Is there any other way to achieve posting data from non-SAP to SAP through HTTPS Post?

       

      Regards,

      Arpita Shetty

      Author's profile photo Abhijeet Kankani
      Abhijeet Kankani

      There are two case :

      1.)With CSRF token --

      By Default Gateway will generate the CSRF token, if any of CUD(Create, Update and Delete) operation we are doing it is mandatory to pass this token(CSRF ).

      So before any CUD operation, Retrieve a CSRF token with a non-modifying request(get method).

       

      Validity of this Token is 30 mins (which can further be altered by Tcode RZ11(Parameter : http/security_session_timeout) might be there is some diffrent mecanism as well

       

      Fetching mechanism :  In client side need to put one parameter X-CSRF-Token('X-CSRF-Token') with the value 'Fetch' is sent along with the non-modifying request.

       

      2.) Without CSRF token --

      without CSRF first we need to override standard behavior of service, in SICF node for each service need to maintain parameter in GUI configuration as below :

      Parameter Name: ~CHECK_CSRF_TOKEN

      Parameter Value: 0/1 (disable/enable)

      And At client level in Header need to pass X in Header

      ('X-Requested-With': 'X')

       

      Regards,

      Abhijeet Kankani

      Author's profile photo Ranjeet Rajan
      Ranjeet Rajan

      Awesome. It worked. Thanks a lot for your help.

      Author's profile photo Sagar Dhange
      Sagar Dhange

      Awesome, This is what I was looking for.

      Thank you For sharing this information.

      Author's profile photo Jimmy Arnold Moreno Nuñez
      Jimmy Arnold Moreno Nuñez

      Hi Peter and everyone.

      I’m trying to call a service on-premise from service task in a cloud workflow but I get this error:

      The XSRF token request to URL 'http://ABC:443/sap/opu/odata/sap/ZGW_MY_SERVICE_SRV/' failed with HTTP status code 401 (Unauthorized) and response body '<html><head><title>Logon Error Message

      In RZ11 Tcode I have the value 0.

      Please, can you help me?

      Author's profile photo Anand Patil
      Anand Patil

      Hi,

      Thanks for the tips. I was facing the same issue of 403 invalid CSRF token when dealing with C4C APIs. After a lot of looking around I found that I need to set only the SESSION ID as Cookie value rather than assigning ${header.set-cookie}. Other way around is to set the HTTP Session Reuse to either Exchange Flow or On Integration Flow.

      Hope it helps someone.

      Thanks again!

      Regards,
      Anand

      Author's profile photo Mahesh Raghavaraju
      Mahesh Raghavaraju

      Hi Anand,

      How to get the SESSION ID ?

      BR, Mahesh R.

      Author's profile photo Ivaylo Mutafchiev
      Ivaylo Mutafchiev

      Hi guys,

       

      this question is old enough, but still making us problems. In my I'm dealing with SAP-to-SAP system REST PUT data. In fact, this is preparation for non-SAP to SAP (S4H - sap_basis rel. 7.53 - 0002), in order to be sure everything is well described to 3th party,

      Scenario:

      1. Build and GET with FETCH for x-csrf-token.
      2. Passed x-csrf-token, set-cookie from GET to POST, also sent x-requested-with = 'X' to both GET and POST. CRSF token seems to be the same. Strange for me here - there were 3 cookie parameters from GET response entity, but only 1 of them was set to header parameters for PUT request entity. Perhaps this is how it should be 🙂

       

      Unfortunately method io_csrf_handler->validate_csrf_token  which is called for PUT inside HANDLE_CSRF_TOKEN is still returned empty ( <> abap_true) and finally returns:

      ~response_line = HTTP/1.0 403 Forbidden

      If I owerwrite this manualy - my PUT request is processed with return code 200.

      In fact, real problem is within kernel call for

      mo_server->validate_xsrf_token(..) ... =>

      _CREATE_AUDIT_EVENTEX BY KERNEL MODULE CreateSecAuditLogEventEx FAIL. 

       

      Tried with paramethers for GUI configuration in SICF - also without success. If I pass 0, then it returns 500 and even do not process HANDLE_REQUEST.

       

      What am I doing wrong?

      Any help is appreciated.

      Thanks,

       

      BR,

      Ivaylo (not a real HTTP-fan)

      Author's profile photo Jeff Bierman
      Jeff Bierman

      Hi,

      I know that this issue is a couple years old now, but I was having the same problem with an invalid x-csrf-token token when calling an SAP API from Cloud-Integration.  The eventual solution to my problem, was to set the HTTP Session Reuse field in the Integration Flow to be "On Exchange".  The default is None, which is causing a csrf token 403 error.

       

      When I set it to "On Integration Flow", it worked fine for the first message, but since I was splitting the inbound message into multiple SAP Calls, only the first one worked.  Subsequent calls failed on csrf-token also.

      HTTP%20Session%20Reuse%20in%20CI

      HTTP Session Reuse in CI