cancel
Showing results for 
Search instead for 
Did you mean: 

CAP Node JS - cds.env.features.fetch_csrf per service

03-22-2022 1:27 PM
carlonnheim Participant
1890 views 5 comments Go to solution
SAP Managed Tags
Subscribe

Hi,

We have a CAP project with a mix of external services. Some require CSRF tokens (SAP backends), some do not require it (non-SAP backends) and some of the latter are not responding well to the "HEAD" requests which are emitted by the SDK to fetch CSRF tokens (fail or cause long delays).

So I need to control this on a per-service level. There is the "cds.env.features.fetch_csrf" flag but it applies across all the services. How can I make it active for a subset of the services? Looking at the sources it seems I might be out of luck here, am I missing something or do I need to patch it and can it be considered for implementation in CAP?

Thanks in advance!

//Carl

Accepted Solutions (1)

Accepted Solutions (1)

OlenaT
Product and Topic Expert
Product and Topic Expert

Hi onnheimc ,

As I replied in your other question:

We are introducing two new configuration options: csrf: true/false and csrfInBatch: true/false which will allow you to configure csrf token handling pro service. Please track our release notes. Global env variable cds.env.features.fetch_csrf will be deprecated.

Regarding your problem with an action call: We have created a task for this, but there is no timeline on it yet. One of our colleagues will get back to you after the task is completed.

Best regards,

Olena

carlonnheim
Participant
0 Likes

That is great news olena_ , many thanks!

//Carl

Answers (2)

Answers (2)

Andrew_Mai
Participant

I used to face this one. My trick is, before calling the API that require the CSRF, I will cds.env.features.fetch_csrf = true; then right after the call success, I will call cds.env.features.fetch_csrf = false; again. Some thing like this:

cds.env.features.fetch_csrf = true;
await callExternalAPI();
cds.env.features.fetch_csrf = false;

So other service will not be impact.

carlonnheim
Participant
0 Likes

Thanks andrew.mai.laidon .

This worked well until calls to services requiring and refusing csrf tokens got interleaved in our scenarios (since it is async another service might start a call before the fetch_csrf token flag gets restored).

I could narrow that by hooking a getter onto the property like so, making it work without conflicts as long as I do not get scenarios where the same execution context interleaves between csrf-requiring and csrf-refusing services. Maybe that helps somebody getting into the same trouble.

// Workaround to disable csrf tokens for a specific call
const noCsrf = Symbol('no_fetch_csrf');
cds.once('bootstrap', app => {
    var fetch_csrf = _.get(cds, 'env.features.fetch_csrf');
    if (fetch_csrf) {
        LOG.debug('*** Mangling the fetch_csrf feature ***');
        // Replace the fetch_csrf value with a custom getter
        Reflect.defineProperty(cds.env.features, 'fetch_csrf', {
            get() {
                if (cds.context[noCsrf]) {
                    LOG.debug('*** CSRF is disabled ***');
                    return false;
                }
                LOG.debug('*** CSRF is untouched ***');
                return fetch_csrf;
            },
        });    
    }
});

// Service calls are surrounded with these
function disableCsrf() {
    cds.context[noCsrf] = true;
}
function enableCsrf() {
    cds.context[noCsrf] = false;
}
Would be really good if the flag could be moved to the individual service level instead of global feature level, any updates vitaly.kozyura ?Thanks!//Carl
vitaly_kozyura
Advisor
Advisor

Hi, Configuring csrf feature for a subset of services is not supported. We consider implementing this. Regards, Vitaly