POSTing Webhook fails with status 214 - NodeJS - (Latency < 1s, sending 200 status)

nodejs
oauth
webhooks

#1

EDIT: Forgot to mention, yes the app has been whitelisted

I have been reading through the various similar threads here but cannot find a solution for my case. I have configured an AWS lambda with an API Gateway which responds in under 1s according to Postman. My Node code is below.

I followed a really good guide from Frederik Willaert
https://www.linkedin.com/pulse/handling-twitter-webhooks-aws-lambda-step-functions-frederik-willaert

module.exports.webhookGET = (event, context, callback) => {
  const appConsumerSecret = 'appConsumerSecret';
  const crcToken = event.query.crc_token;

  if (!crcToken) {
      return callback(null, { statusCode: 400 });
  }

  try {
      const crcTokenHash = computeHmac('sha256', appConsumerSecret, crcToken);

      // wait for promise to resolve before sending response
      crcTokenHash.then((finalCRCTokenHash) => {
        const response = {
            statusCode: 200,
            body: JSON.stringify({ response_token: "sha256=" + finalCRCTokenHash })
        };

        callback(null, response);

      })

  } catch (error) {
      return callback(null, { statusCode: 400 });
  }
}

function computeHmac(algorithm, key, payload) {
    const hmac = crypto.createHmac(algorithm, key);

    return new Promise((resolve, reject) => {
        hmac.on('readable', () => {
            const data = hmac.read();
            if (!data) return reject("No data");
            return resolve((data).toString('base64'));
        });
        hmac.write(payload);
        hmac.end();
    })
}

If I open the API endpoint in my browser and pass a query string, e.g.

https://xxxxxxxxxxxxxxxxx.amazonaws.com/dev/webhook/?crc_token=test

I get a 200 response:

{
statusCode: 200,
body: "{"response_token":"sha256=b/ntLgVhZchtBCeefIB0ym7lB/Q9FI5HnMXJk4G8ZAU="}"
}

When POSTing
the callback URL I am doing so in the following format using Postman => Import => Paste raw text

Then I modify the Authorization to use OAuth 1.0 and add the keys

curl -X POST \

https://api.twitter.com/1.1/account_activity/webhooks.json \

-H 'content-type: application/x-www-form-urlencoded' \

-d url=https://xxxxxxxxxxxxxxxxxxxx.amazonaws.com/dev/webhook

Anyone have any idea what I am doing wrong? Any help would be much appreciated!


#2

Fixed my issue, posting in case it helps someone else. My bad I didn’t interpret the docs properly.

The issue was my response format. I was returning the response_token as part of the body and not as a plain JSON response.

FYI I am using serverless to deploy/manage my AWS Lambda, so I needed to update the response headers to application/json. Would be more straightforward with a regular Node/Express server I’m sure.

functions:
  webhookGET:
    handler: handler.webhookGET
    events:
      - http:
          path: /webhook
          method: get
          integration: lambda
          response:
            headers:
              Content-Type: "'application/json'"

Also instead of stringifying the response_token in the body I am just returning a plain object, e.g.

// edit of my initial code
crcTokenHash.then((finalCRCTokenHash) => {
        // return JSON
        callback(null, { response_token: "sha256=" + finalCRCTokenHash });
      })

So my response looks like:

{
  "response_token": "sha256=XXXXXXXXXXXXXXXXXXXXXXXX="
}

as opposed to what it was previously:

{
  "statusCode": 200,
  "body": "{\"response_token\":\"sha256=XXXXXXXXXXXXXXXXXXXXXXXX=\"}"
}

#3

Great to hear you got it figured out, thanks for sharing the solution! :thumbsup: