서명 검증
모든 Webhook 요청에 포함되는 X-Signature 헤더를 사용한 HMAC-SHA256 서명 검증 방법을 안내합니다.
ClawOps는 모든 웹훅 요청에 X-Signature 헤더를 포함합니다. HMAC-SHA256 기반으로 요청의 무결성을 검증할 수 있습니다.
프로덕션 환경에서는 반드시 서명을 검증하세요. 서명 검증을 하지 않으면 외부에서 위조된 요청을 보낼 수 있습니다.
이 서명 검증 방법은 수신 전화(VoiceML), Status Callback, Message Webhook 모두에 동일하게 적용됩니다.
서명 생성 알고리즘
- 웹훅 URL 문자열로 시작
- 파라미터를 키 사전순(알파벳)으로 정렬
- 각 key + value를 URL 뒤에 순서대로 연결
HMAC-SHA256(signingKey, data)결과를 Base64 인코딩
Python 수동 구현
import hmac, hashlib, base64
from flask import Flask, request
app = Flask(__name__)
SIGNING_KEY = "your_signing_key"
@app.route("/webhook", methods=["POST"])
def webhook():
signature = request.headers.get("X-Signature", "")
params = request.form.to_dict()
url = request.url
# 파라미터를 키 사전순으로 정렬 후 URL 뒤에 연결
sorted_params = sorted(params.items())
data = url + "".join(f"{k}{v}" for k, v in sorted_params)
# HMAC-SHA256 서명 생성
expected = base64.b64encode(
hmac.new(SIGNING_KEY.encode(), data.encode(), hashlib.sha256).digest()
).decode()
if not hmac.compare_digest(signature, expected):
return "Unauthorized", 401
# 서명 검증 성공
call_id = request.form["CallId"]
...SDK를 사용한 검증
ClawOps Python SDK의 webhooks.verify() 메서드를 사용하면 서명 검증을 간결하게 처리할 수 있습니다.
from clawops import ClawOps, WebhookVerificationError
client = ClawOps()
@app.route("/webhook", methods=["POST"])
def webhook():
try:
client.webhooks.verify(
url="https://my-app.com/webhook",
params=request.form.to_dict(),
signature=request.headers["X-Signature"],
signing_key="your_signing_key",
)
except WebhookVerificationError:
return "Unauthorized", 401
call_id = request.form["CallId"]
...Signing Key는 대시보드 > 설정 > Webhook에서 확인할 수 있습니다. API Key와는 별도의 값입니다.