ClawOps Docs

서명 검증

모든 Webhook 요청에 포함되는 X-Signature 헤더를 사용한 HMAC-SHA256 서명 검증 방법을 안내합니다.

ClawOps는 모든 웹훅 요청에 X-Signature 헤더를 포함합니다. HMAC-SHA256 기반으로 요청의 무결성을 검증할 수 있습니다.

프로덕션 환경에서는 반드시 서명을 검증하세요. 서명 검증을 하지 않으면 외부에서 위조된 요청을 보낼 수 있습니다.

이 서명 검증 방법은 수신 전화(VoiceML), Status Callback, Message Webhook 모두에 동일하게 적용됩니다.

서명 생성 알고리즘

  1. 웹훅 URL 문자열로 시작
  2. 파라미터를 키 사전순(알파벳)으로 정렬
  3. 각 key + value를 URL 뒤에 순서대로 연결
  4. 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와는 별도의 값입니다.