Answered

I cannot verify in topic of Secure Webhooks

  • 12 October 2021
  • 5 replies
  • 446 views

Userlevel 1

I use NodeJs with Express. I looked the code in  https://glitch.com/edit/#!/tf-webhook-receiver?path=server.js%3A1%3A0 . 

 

I think, He convert req.body from raw data as buffer (binary) to string and send to method that create Hmac-sha256 and then base 64.

 

I can not use bodyParser.raw({ type: 'application/json' }) from example link in each router because I register app.use(express.json) in application layer, it mean my whole project will receive req as JSON Object.

 

So I do by using some concept in example code by trying to convert req.body being object to JSON String and finally convert to buffer before create hash to compare with req.header('Typeform-Signature').

const encodedJsonObject = Buffer.from(JSON.stringify(req.body, null, 0));

const hash = crypto.createHmac('sha256',TYPEFORM_SECRET)

.update(encodedJsonObject)

.digest('base64');

or

const encodedJsonObject = Buffer.from(JSON.stringify(req.body));

const hash = crypto.createHmac('sha256', TYPEFORM_SECRET)

.update(encodedJsonObject)

.digest('base64');

 

It still don’t work even thought at .(update) I directly to put JSON.stringify(req.body).

How should I do? or Am I doing something wrong?

icon

Best answer by picsoung 12 October 2021, 23:50

View original

5 replies

Userlevel 7
Badge +5

Hi @wuttichow Thanks for stopping by the community. It looks like you might be using some custom code here, but @picsoung can verify this and any issues for me!

Userlevel 7
Badge +5

Hi @wuttichow 👋

Thank you for your question. I just added a file server_global_bodyparser.js file to the example project that should cover your situation.

What does it do?

 

I am using the verify option from bodyParser, and pass the rawBody only if the request comes from Typeform.

//custom verifier function, only to requests from Typeform
const rawBodySaver = (req, res, buf, encoding) =>{
if (req.headers['user-agent'] ==='Typeform Webhooks' && req.headers['typeform-signature'] && buf && buf.length) {
req.rawBody = buf.toString(encoding || 'utf8');
}
}

const options = {
verify: rawBodySaver
};

app.use(bodyParser.json(options));

Then in our endpoint

// security check, let's make sure request comes from typeform
const signature = request.headers['typeform-signature']
const isValid = verifySignature(signature, request.rawBody.toString())

if (!isValid) {
throw new Error('Webhook signature is not valid, someone is faking this!');
}

// send 200 status back, and notifies typeform 👌
response.sendStatus(200)

// extract details from webhook payload, no more JSON.parse needed
const { event_type, form_response } = request.body;


Hope it helps 🙂
Let us know if you have more questions.

Userlevel 7
Badge +5

Thank you so much, @picsoung !!

Userlevel 1

Thank you for all support. I can do it now.

Userlevel 7
Badge +5

Glad to hear it’s working, @wuttichow !

Reply