Skip to main content

CSRF Fetching

Default Behaviour

The SAP Cloud SDK fetches a CSRF token for non GET requests per default. This is done for all clients that the SAP Cloud SDK provides:

If the target system does not require a token you can disable the fetching as discussed in the sections:

In order to retrieve a token the SAP cloud SDK makes multiple calls. First it makes a request using the resource URL adding a / in the end:

Request:             HEAD /resource/path/
Request Header: X-CSRF-Token=fetch

If this returns a token, execute the request with the token. If not, make a second call without the /:

Request:             HEAD /resource/path
Request Header: X-CSRF-Token=fetch

If this returns a token, execute the request with the token. If this also does not yield a token, the request is executed without an additional token. Note that the SAP Cloud SDK consider SET-COOKIE headers provided the requests returning the tokens.

Most systems will return a CSRF token independent of an additional / in the end. However, we saw issues for SAP S/4HANA OnPremise systems which required the / and other systems not being able to handle the slash. If performance is relevant you should check:

  • Does the system need a CSRF token? If not disable the fetching.
  • Does the system fail to return a CSRF with a /? Adjust the token fetching via a middleware.
note

The SAP Cloud SDK will discontinue fetching CSRF tokens per default. From version 4 on you will need to add the csrf() middleware to enable fetching. Also, a failure in token fetching will stop the request execution and not silently be ignored.

Changing the Default

If the way the SAP Cloud SDK fetches the CSRF token does not fit your needs you can replace the default using a middleware. The SAP Cloud SDK offers a default implementation which allows minor adjustments as described here:

In this section you will learn how to implement a custom middleware which does only a single request without a slash. We will use the OData client for illustration but everything applies to the other clients as well. You disable the token fetching and add a middleware:

const { businessPartnerApi } = businessPartnerService();
businessPartnerApi
.requestBuilder()
.update(businessPartner)
.middleware([customCsrf])
.skipCsrfTokenFetching();

function customCsrf(options: HttpMiddlewareOptions) {
return requestConfig => {
const csrfToken = ''; //add your logic
requestConfig.headers['x-csrf-token'] = csrfToken;
options.fn(requestConfig);
};
}

A basic implementation for fetching a token using a single request without a slash in the end could look like:

function customCsrf(options: HttpMiddlewareOptions) {
return async requestConfig => {
const requestConfigCsrf = {
method: 'head',
headers: {
...requestConfig.headers, //Authentication headers are in here
'x-csrf-token': 'Fetch',
'content-length': 0
},
url: requestConfig.url.replace(/\/$/, '')
};

const response = await axios.request(requestConfigCsrf);

requestConfig.headers['x-csrf-token'] = response.headers['x-csrf-token'];

return options.fn(requestConfig);
};
}

This implementation is meant as an example to illustrate the concept. It misses many things like setting cookies provided by the first request or checking the request method.