Client.request fails on a specific endpoint

Hi,

I’m facing an extremely weird error - I can’t access one specific point using client.request, under specific conditions.
We have a Marketplace app called Asana Connect, which is basically an integration between Freshdesk and Asana. As we’ve decided to update the app with some new features, we’ve discovered that one of the parts of the existing code stopped working for seemingly no reason. It has to do with the Asana Events API, which allows us to poll an entity for recent changes. The way it works is as follows: if you’re accessing the endpoint for the first time, Asana returns a 412 error with a new sync token attached. After that, if we access the endpoint again with the sync token, the API should return the list of events that happened after the token was generated, and also the updated token.
For whatever reason, since at least early December 2022, we can’t access the Events API with a token - the API always returns 401 Unauthorized. Every other endpoint works correctly, both in front-end and serverless components, even calling the Events API without a sync token works fine, but as soon as I attach a sync token to the request, the authorization fails. We’re using the built-in OAuth2 handler for Freshdesk apps, so I suspected that the issue might be with that. However, as I generated a fresh bearer token and hardcoded it into the request function (removing the “isOauth” flag), the problem persisted - I still get the same 401 error upon hitting the Request API with a valid sync token. For investigation purposes I’ve recreated the process in a standalone Node.js script, and it worked just fine. Then I’ve tried switching the client.request for the “request-promise” NPM package within the existing Freshdesk app, which also worked correctly. The problem is observed exclusively when trying to use client.request, regardless of whether we’re using the OAuth flow or not.
Below is some logs from a testing attempt. I’m logging the request URL, the headers object, and the response. As you can see, the same exact process works without the sync token and then fails when I attach a sync token to the request.


Just in case, here’s an example without a token - as you can see, in this case, the process fails on the first request.

Here’s the part of the code that gets the updates from a resource:

function asanaUpdates(data){
  const asana = new Asana(data.workspace);
  return new Promise((resolve, reject) => {
    asana.getEvents(data.gid, data.token).then(res => {
      var events = res.data;
      var event_count = 0;
      events.forEach(event => {
        if (event.type == "story" && event.action == "added" && event.resource.type == "comment") {
          if (event.resource.text.substr(0, 11) !== "[Freshdesk]") {
            createNoteInFD(data, event);
            event_count++;
          }
        }
      });
      $db.update(data.ticket_id.toString(), "set", {"token": res.sync}).then(() => {
        resolve(event_count)
      }, err => {
        console.error("Couldn't update the token in DB!", err);
      });
    }, function(err){
      if (err.status == 412) {
        data.token = err.response.sync;
        resolve(asanaUpdates(data));
      } else {
        console.log(err)
        reject(err);
      }
    });
  });
}

Here’s the GET call function from the Asana API class:

get(endpoint){
  return new Promise(function(response, reject){
    $request.get(`https://app.asana.com/api/1.0/${endpoint}`, {
      headers: {
        "Authorization": "Bearer <%= access_token %>",
        "Content-Type": "application/json"
      },
      isOAuth: true
    }).then(function(res){
      let data = JSON.parse(res.response);
      response(data);
    }, function(err){
      let err_obj = {
        status: err.status,
        response: JSON.parse(err.response)
      };
      reject(err_obj);
    });
  });
}

getEvents(gid, token = null){
  return this.get(`events?resource=${gid}&sync=${token}`);
}

Can anyone tell me what exactly is going on? If not, can we use this example to justify switching from client.request to a third-party request library in a Marketplace app?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.