Skip to main content
서버로 전송하는 모든 요청(웹훅 전송 및 도구 엔드포인트 호출)에는 X-ThunderPhone-Signature 헤더에 HMAC-SHA256 서명이 포함됩니다. 검증을 한 번만 올바르게 구현하고 모든 핸들러에서 동일한 헬퍼를 사용합니다.

알고리즘

  1. 원본 요청 본문, 즉 ThunderPhone이 POST한 정확한 바이트를 읽습니다.
  2. hmac_sha256(secret, body).hexdigest()를 계산합니다.
  3. X-ThunderPhone-Signature상수 시간으로 비교합니다. (일반적인 문자열 비교는 타이밍 정보를 노출합니다.)
ThunderPhone은 전송하는 정확한 바이트에 서명하므로 원본 본문을 검증하면 항상 작동합니다. 이 바이트는 페이로드의 정규 JSON 직렬화이기도 합니다. 키는 알파벳순으로 정렬되고, 구분 기호는 공백 없는 (,:) 형식이며, UTF-8을 사용합니다. 프레임워크가 파싱된 JSON만 제공하는 경우에도 완전히 동등한 두 번째 방법을 사용할 수 있습니다. 정규 형식으로 다시 직렬화한 후 해당 값으로 HMAC을 계산합니다.
원본 본문을 사용하는 것이 좋습니다. 단계가 하나 줄어들고 일부 언어에서 발생하는 JSON 숫자 왕복 변환 문제의 영향을 받지 않습니다.

어떤 시크릿을 사용해야 하나요?

시크릿은 시크릿 관리자 또는 환경 변수에 저장하고, 절대 커밋하지 마세요.

참조 구현

다음 네 가지 구현은 모두 원본 요청 본문을 검증합니다.

프레임워크별 연결

도구 호출 검증

에이전트가 함수 도구를 직접 호출하는 경우 (도구에 endpoint가 있는 경우), 요청에는 구성한 endpoint.headers와 함께 두 개의 ThunderPhone 헤더가 포함됩니다.
  • X-ThunderPhone-Call-ID — 진행 중인 통화의 숫자 ID입니다.
  • X-ThunderPhone-Signature — 정확한 요청 본문 바이트에 대해 조직 수준 웹훅 시크릿을 키로 사용하는 HMAC-SHA256입니다.
동일한 verify() 헬퍼를 수정 없이 사용할 수 있지만, 다음 두 가지 차이점이 있습니다.
  1. GET / DELETE 도구에는 본문이 없습니다. 인수는 쿼리 매개변수로 전달되며, 서명은 빈 바이트 문자열에 대해 계산됩니다. 따라서 Python에서는 verify(b"", sig, secret), Node에서는 verify(Buffer.alloc(0), sig, secret)를 사용합니다. 쿼리 문자열을 해싱하지 마십시오.
  2. 레거시 웹훅이 구성되지 않은 조직에는 조직 시크릿이 없습니다. 이 경우 도구 호출에는 X-ThunderPhone-Call-ID만 포함되고 서명 헤더는 포함되지 않습니다. 서명 시크릿을 받으려면 레거시 웹훅 (PUT /v1/webhook)을 구성하거나, endpoint.headers를 통해 자체 헤더로 도구 호출을 인증하십시오.
웹훅 모드 도구 디스패치(endpoint가 없는 도구이며 telephony.tool / web.tool로 조직 웹훅에 전달됨)는 일반적인 서명된 웹훅입니다. 위의 표준 방식을 적용하십시오. 두 요청 형식은 함수 도구를 참조하십시오.

일반적인 주의 사항

본문을 파싱한 후 JSON 라이브러리의 기본값(, / : 뒤 공백, 삽입 순서 키)으로 다시 덤프하면 바이트가 달라져 HMAC이 손상됩니다. 원시 본문을 검증하세요. 다시 직렬화해야 하는 경우에는 정렬된 키, 압축 구분자, UTF-8이라는 정규 형식과 정확히 일치시켜야 합니다.
Express의 express.json() 미들웨어는 본문 스트림을 소비하므로 원시 바이트를 잃게 됩니다. 웹훅 경로에는 express.raw()를 사용하거나 사전 미들웨어에서 원시 본문을 버퍼링하세요. NestJS / Koa도 동일합니다. 해당 프레임워크의 “raw body” 문서를 확인하세요.
JS의 expected === signature 또는 Python의 expected == signature는 타이밍이 가변적인 비교입니다. 각각 crypto.timingSafeEqual 또는 hmac.compare_digest를 사용하세요. 성능 차이는 없습니다.
직접 도구 엔드포인트 호출은 /v1/developer/webhook-endpoints의 엔드포인트별 시크릿이 아니라 조직 수준 웹훅 시크릿(GET /v1/webhook)으로 서명됩니다. 동일한 verify() 함수를 재사용하되, 도구 경로에는 조직 시크릿을 전달해야 합니다.
본문이 없는 도구 메서드에서는 서명이 빈 바이트 문자열을 대상으로 하므로 하나의 범용 방식이 유지됩니다. 즉, 어떤 내용이든 원시 요청 본문에 HMAC을 적용합니다. URL이나 쿼리 문자열을 해싱하면 절대 일치하지 않습니다.
검증 실패 시 200을 반환하면 핸들러가 재전송 공격의 대상이 됩니다. 검증에 실패하면 항상 2xx가 아닌 응답을 반환하세요.

다음 단계

웹훅 개요

전달 의미 체계, 재시도, 소스 IP.

웹훅 엔드포인트

여러 URL을 관리하고 시크릿을 교체합니다.

함수 도구

두 가지 도구 호출 경로와 요청 형식입니다.

도구 통합

도구 기반 통합을 처음부터 끝까지 구축합니다.