From 8e45656c8603531fcd61312a710261b99bba8dd1 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Sun, 19 Jan 2025 22:25:23 +0530 Subject: [PATCH] fix: added webhook verify token for security --- .../crm_exotel_settings.json | 15 +++++++++++- crm/integrations/exotel/handler.py | 23 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json b/crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json index 98382626d..a4fc1bf61 100644 --- a/crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json +++ b/crm/fcrm/doctype/crm_exotel_settings/crm_exotel_settings.json @@ -10,6 +10,8 @@ "record_call", "section_break_kfez", "account_sid", + "column_break_qwfn", + "webhook_verify_token", "section_break_iuct", "api_key", "column_break_hyen", @@ -70,12 +72,23 @@ "fieldname": "record_call", "fieldtype": "Check", "label": "Record Call" + }, + { + "fieldname": "column_break_qwfn", + "fieldtype": "Column Break" + }, + { + "depends_on": "enabled", + "fieldname": "webhook_verify_token", + "fieldtype": "Data", + "label": "Webhook Verify Token", + "mandatory_depends_on": "enabled" } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2025-01-15 19:31:00.310049", + "modified": "2025-01-19 22:19:20.713970", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Exotel Settings", diff --git a/crm/integrations/exotel/handler.py b/crm/integrations/exotel/handler.py index 7d3301a8c..4ffc00b47 100644 --- a/crm/integrations/exotel/handler.py +++ b/crm/integrations/exotel/handler.py @@ -1,5 +1,3 @@ -import json - import bleach import frappe import requests @@ -8,10 +6,20 @@ from crm.integrations.api import get_contact_by_phone_number +# Endpoints for webhook + +# Incoming Call: +# /api/method/crm.integrations.exotel.handler.handle_request?key= + +# Exotel Reference: +# https://developer.exotel.com/api/ +# https://support.exotel.com/support/solutions/articles/48283-working-with-passthru-applet + # Incoming Call @frappe.whitelist(allow_guest=True) def handle_request(**kwargs): + validate_request() if not is_integration_enabled(): return @@ -149,6 +157,17 @@ def get_exotel_settings(): return frappe.get_single("CRM Exotel Settings") +def validate_request(): + # workaround security since exotel does not support request signature + # /api/method/?key= + webhook_verify_token = frappe.db.get_single_value("CRM Exotel Settings", "webhook_verify_token") + key = frappe.request.args.get('key') + is_valid = key and key == webhook_verify_token + + if not is_valid: + frappe.throw(_("Unauthorized request"), exc=frappe.PermissionError) + + @frappe.whitelist() def is_integration_enabled(): return frappe.db.get_single_value("CRM Exotel Settings", "enabled", True)