I cannot verify in topic of Secure Webhooks | Community
Skip to main content
Answered

I cannot verify in topic of Secure Webhooks

  • October 12, 2021
  • 5 replies
  • 507 views

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?

Best answer by picsoung

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.

View original

5 replies

Liz
Community Team
Forum|alt.badge.img+5
  • Tech Community Advocate
  • 14919 replies
  • October 12, 2021

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!


picsoung
Typeform
Forum|alt.badge.img+5
  • Developer Advocate @ Typeform
  • 389 replies
  • Answer
  • October 12, 2021

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.


Liz
Community Team
Forum|alt.badge.img+5
  • Tech Community Advocate
  • 14919 replies
  • October 12, 2021

Thank you so much, @picsoung !!


  • Author
  • Explorer
  • 3 replies
  • February 14, 2022

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


Liz
Community Team
Forum|alt.badge.img+5
  • Tech Community Advocate
  • 14919 replies
  • February 14, 2022

Glad to hear it’s working, @wuttichow !


Reply