I'm trying to accept form responses from Typeform using Python/Django/DRF and am having trouble authenticating the webhook request due to not being able to get the hashes to match.
Here are the instructions from Typeform:
11. Using the HMAC SHA-256 algorithm, create a hash (using created_token as a key) of the entire received payload as binary.22. Encode the binary hash in base64 format.33. Add prefix sha256= to the binary hash.44. Compare the created value with the signature you received in the Typeform-Signature header from Typeform.
authentication.py
1class TypeformAuthentication(authentication.BaseAuthentication):2 def authenticate(self, request):3 typeform_signature = request.META.get('HTTP_TYPEFORM_SIGNATURE')4 data = request.body5 secret_key = os.environ.get('TYPEFORM_SECRET_KEY')67 if not typeform_signature:8 return None910 if typeform_signature:11 hash = hmac.new(bytes(secret_key, encoding='utf-8'), data, hashlib.sha256)12 actual_signature = 'sha256={}'.format(base64.b64encode(hash.digest()).decode())13 user = User.objects.get(username='typeform-user')14 if actual_signature == typeform_signature:15 return(user, None)16 else:17 raise exceptions.AuthenticationFailed('Typeform signature does not match.')18 else:19 return None
Example payload
1{2 "event_id": "01DTXE27VQSA3JP8ZMP0GF9HCP",3 "event_type": "form_response",4 "form_response": {5 "form_id": "OOMZur",6 "token": "01DTXE27VQSA3JP8ZMP0GF9HCP",7 "landed_at": "2019-11-30T05:55:46Z",8 "submitted_at": "2019-11-30T05:55:46Z",9 "definition": {10 "id": "OOMZur",11 "title": "Auto Liability (New Company)",12 "fields": [13 {14 "id": "GnpcIrevGZQP",15 "title": "What is your business name?",16 "type": "short_text",17 "ref": "3e60e064-f14c-4787-9968-0358e8f34468",18 "properties": {}19 }20 ]21 },22 "answers": [23 {24 "type": "text",25 "text": "Lorem ipsum dolor",26 "field": {27 "id": "GnpcIrevGZQP",28 "type": "short_text",29 "ref": "3e60e064-f14c-4787-9968-0358e8f34468"30 }31 }32 ]33 }34}
Typeform Generated Hash
sha256=jdzKuFkijyBIMvmGyveHfcfzcNXUeQCuveNGP6CEdXk=
authentication.py Generated Hash