Choorai
결제/외부 연동 핵심 이슈

Webhook 서명 검증 실패 해결하기

결제/외부 이벤트 웹훅에서 signature verification failed가 발생하면 이벤트가 무시되어 데이터 불일치가 생길 수 있습니다.

TL;DR (핵심 요약)

1) raw body 기준으로 서명 검증 2) 환경별 webhook secret 확인 3) 재시도/중복 처리(idempotency) 적용

심각

Webhook signature verification failed

원인

웹훅 payload 무결성 검증에 실패했습니다. raw body 변형, 시크릿 불일치, 헤더 누락이 흔한 원인입니다.

해결책
  1. JSON 파싱 전에 raw body로 서명 검증
  2. 운영/테스트 webhook secret 혼용 여부 확인
  3. 공급자 문서의 서명 알고리즘/헤더 형식 준수
  4. 중복 이벤트 대비 idempotency 키 처리

검증 포인트

Express + Stripe 예시
import express from 'express';
import Stripe from 'stripe';

const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || '');

app.post('/webhook/stripe', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['stripe-signature'];
  const secret = process.env.STRIPE_WEBHOOK_SECRET || '';

  try {
    const event = stripe.webhooks.constructEvent(req.body, String(signature), secret);
    // TODO: handle event with idempotency check
    res.status(200).send('ok');
  } catch (err) {
    res.status(400).send('signature verification failed');
  }
});

주의

body parser를 먼저 적용하면 raw body가 변경되어 서명 검증이 실패할 수 있습니다. webhook 라우트에는 raw parser를 우선 적용하세요.

Prerequisites

  • 웹훅 공급자(Stripe/GitHub 등)의 서명 검증 문서를 확인할 수 있어야 합니다.
  • 서버에서 원본 request body(raw body)를 읽을 수 있어야 합니다.
  • 웹훅 시크릿 키를 안전하게 환경변수로 관리해야 합니다.

Validation

  1. 정상 웹훅 요청에서 서명 검증이 성공합니다.
  2. 잘못된 시크릿 또는 변조된 payload에서는 4xx로 거부됩니다.
  3. 재시도 요청(idempotency) 처리로 중복 사이드이펙트가 발생하지 않습니다.

Troubleshooting

  • JSON 파싱 전에 raw body 기준으로 서명을 검증하세요.
  • 운영/스테이징 웹훅 시크릿이 섞여 있지 않은지 확인하세요.
  • 타임스탬프 허용 오차와 재생 공격 방지 설정을 점검하세요.

References

관련 문서

마지막 업데이트: 2026년 2월 22일 · 버전: v0.0.1

피드백 보내기

입력한 내용으로 새 이슈 페이지를 엽니다.

GitHub 이슈로 보내기