cloud-sdk-js icon indicating copy to clipboard operation
cloud-sdk-js copied to clipboard

Fetching csrf token fails

Open pwasem opened this issue 5 months ago • 1 comments

Describe the Bug

This is an indirect issue which originates from builtin CSRF-Token Handling in sap cap.

Fetching the csrf token fails because the on-premise system does return http status 405 when fetching the token and also does not return a x-csrf-token header in the response, but only set-header (w/ the cookie).

As seen in the code https://github.com/SAP/cloud-sdk-js/blob/ac506e453805d13c63e6c19ff55754b9082317d4/packages/http-client/src/csrf-token-middleware.ts#L140C11-L140C48 the cloud sdk will only check for x-csrf-token not for set-header.

Is this an expected issue and / or is there any way to get around this?

Related cds config:

{
  "requires": {
    "CE_QUALITYNOTIFICATION_0001": {
      "kind": "odata",
      "model": "srv/external/CE_QUALITYNOTIFICATION_0001",
      "csrf": {
        "method": "get"
      },
      "credentials": {
        "path": "/sap/opu/odata4/sap/api_qualitynotification/srvd_a2x/sap/qualitynotification/0001"
      }
    }
  }
}

Related error logs:

info backend-proxy-middleware /odata/v4/documents/Documents(ID=60298dbf-f89f-4903-b81e-b73bcf517e64,IsActiveEntity=true)/DocumentsService.createQualityNotification
(node:42806) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[odata] [INFO] POST /odata/v4/documents/Documents(ID=60298dbf-f89f-4903-b81e-b73bcf517e64,IsActiveEntity=true)/DocumentsService.createQualityNotification
[DocumentsService] [INFO] createQualityNotification {
  ...
}
[cds] [INFO] connect to CE_QUALITYNOTIFICATION_0001 > odata {
  path: '/sap/opu/odata4/sap/api_qualitynotification/srvd_a2x/sap/qualitynotification/0001',
  url: '...',
  authentication: '...',
  username: 'RFC_USER',
  password: '...',
  queries: { 'sap-client': '...' },
  isTrustingAllCertificates: true,
  queryParameters: { 'sap-client': '...' }
}
[2025-06-13T09:58:26.757Z] DEBUG    (authorization-header): Getting authentication related headers for authentication type: BasicAuthentication
[2025-06-13T09:58:26.757Z] WARN     (http-agent): "isTrustingAllCertificates" property in the provided destination is set to "true". This is highly discouraged in production.
[2025-06-13T09:58:26.758Z] DEBUG    (jwt): JWT zid is: undefined, app_tid is: undefined.
[2025-06-13T09:58:26.930Z] WARN     (csrf-middleware): Failed to get CSRF token from  URL: /sap/opu/odata4/sap/api_qualitynotification/srvd_a2x/sap/qualitynotification/0001/QualityNotification/.
[2025-06-13T09:58:27.040Z] WARN     (csrf-middleware): Failed to get CSRF token from  URL: /sap/opu/odata4/sap/api_qualitynotification/srvd_a2x/sap/qualitynotification/0001/QualityNotification.
[2025-06-13T09:58:27.041Z] DEBUG    (http-client): Execute 'POST' request with target: /sap/opu/odata4/sap/api_qualitynotification/srvd_a2x/sap/qualitynotification/0001/QualityNotification.
The headers of the request are:
authorization:<DATA NOT LOGGED TO PREVENT LEAKING SENSITIVE DATA>
accept:application/json,text/plain
content-type:application/json
content-length:77
x-correlation-id:42738df5-d0a8-4be6-bb16-9493ce712842
x-correlationid:42738df5-d0a8-4be6-bb16-9493ce712842
[remote] [WARN] Error: Error during request to remote service: CSRF token is missing
    at run (/Users/some/project/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js:233:31)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async RemoteService.on_handler (/Users/some/project/node_modules/@sap/cds/libx/_runtime/remote/Service.js:273:20)
    at async next (/Users/some/project/node_modules/@sap/cds/lib/srv/srv-dispatch.js:61:17)
    at async RemoteService.handle (/Users/some/project/node_modules/@sap/cds/lib/srv/srv-dispatch.js:59:10)
    at async DocumentsService.onCreateQualityNotification (/Users/some/project/srv/documents/service.ts:274:19)
    at async next (/Users/some/project/node_modules/@sap/cds/lib/srv/srv-dispatch.js:61:17)
    at async DocumentsService.handle (/Users/some/project/node_modules/@sap/cds/lib/srv/srv-dispatch.js:59:10) {
  statusCode: 502,
  reason: [AxiosError]
}
[DocumentsService] [ERROR] Error submitting quality notification {
  error: {
    code: '/IWBEP/CM_V4H_RUN/043',
    message: 'CSRF token is missing',
    '@SAP__common.ExceptionCategory': 'CSRF_Token_Missing'
  }
}

Steps to Reproduce

  1. using @sap/cds
  2. CSRF-Token Handling
  3. Trigger remote request to on-premise system not setting x-csrf-token header, but only set-cookie

Expected Behavior

Ideally the sdk should also handle set-cookie header

Screenshots

No response

Used Versions

package version
@cap-js/asyncapi 1.0.3
@cap-js/cds-test 0.3.0
@cap-js/cds-types 0.11.0
@cap-js/db-service 2.1.2
@cap-js/hana 2.1.1
@cap-js/openapi 1.2.3
@cap-js/sqlite 2.0.1
@sap/cds 9.0.3
@sap/cds-compiler 6.0.12
@sap/cds-dk 9.0.5
@sap/cds-fiori 2.0.1
@sap/cds-mtxs 3.0.1
Node.js v22.16.0
rpm 11.4.1
@sap-cloud-sdk/connectivity 4.0.2
@sap-cloud-sdk/http-client 4.0.2
@sap-cloud-sdk/resilience 4.0.2

Code Examples

      const qn = await cds.connect.to('CE_QUALITYNOTIFICATION_0001')

      // WORKAROUND: manually fetch CSRF token before sending POST request
      // Fetching token via config fails because of 405 status code and missing x-csrf-token header
      // See: https://cap.cloud.sap/docs/node.js/remote-services#advanced-configuration
      const cookie = await qn
        .send('HEAD', 'QualityNotification', {
          'x-csrf-token': 'fetch',
        })
        .then((response: AxiosResponse) => {
          const { headers } = response
          return headers['set-cookie']
        })
        .catch((error: unknown) => {
          const { reason: { response: { headers } } } = error as Error & {
            reason: {
              response: AxiosResponse
            }
          }
          return headers['set-cookie']
        })

      const res = await qn.send<object>('POST', 'QualityNotification', {
        NotificationType: 'F1',
        NotificationText: 'Short description of the issue',
      }, {
        cookie,
      })

Log File

No response

Affected Development Phase

Development

Impact

Impaired

Timeline

No response

Additional Context

No response

pwasem avatar Jun 16 '25 08:06 pwasem

Hi @pwasem ,

The SDK, by design, always checks for the x-csrf-token header first, and only if it's present does it proceed to check for the set-cookie. So your workaround makes sense in this context.

We do offer a way to override the default CSRF implementation using middlewares, as described here.

deekshas8 avatar Jun 16 '25 13:06 deekshas8

Closing this issue due to inactivity.

KavithaSiva avatar Sep 30 '25 12:09 KavithaSiva