Oferta de lançamento: −50 % no seu primeiro pagamento, até 30 de novembro.Ver a oferta →
webhook·toolkit

Slack request signature verification failing (X-Slack-Signature)

Slack signs Events API calls, slash commands and interactive payloads with your app's Signing Secret. The signature is v0= followed by the hex HMAC-SHA256 of the string v0:{X-Slack-Request-Timestamp}:{raw body}.

Open the Slack webhook tester →

The check

Node.js
import crypto from 'node:crypto';

function verifySlack(rawBody, headers, signingSecret) {
  const ts = headers['x-slack-request-timestamp'];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 60 * 5) return false; // replay window
  const expected = 'v0=' + crypto.createHmac('sha256', signingSecret).update(`v0:${ts}:${rawBody}`).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(headers['x-slack-signature'] || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Python
import hashlib, hmac, time

def verify_slack(raw_body: bytes, headers, signing_secret: str) -> bool:
    ts = headers['X-Slack-Request-Timestamp']
    if abs(time.time() - int(ts)) > 60 * 5:
        return False
    base = b'v0:' + ts.encode() + b':' + raw_body
    expected = 'v0=' + hmac.new(signing_secret.encode(), base, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, headers.get('X-Slack-Signature', ''))

Cause 1: slash commands and interactivity are form-encoded

Slash commands and interactive components arrive as application/x-www-form-urlencoded. If a form parser runs first, the raw string is gone. Keep the raw body for these routes and parse it only after the check.

Cause 2: the wrong secret

Use the Signing Secret from the app's Basic Information page. The bot token (xoxb-…) and the legacy verification token are not signing keys.

Cause 3: an old timestamp

Slack recommends rejecting requests whose timestamp is more than five minutes away from your clock, to block replays. A server with a drifting clock rejects valid requests; sync it with NTP.

Perguntas frequentes

Should I verify requests from Slack's retries too?

Yes. Retries are signed like the first delivery and carry an X-Slack-Retry-Num header. Verify them the same way, then deduplicate on the event_id so the work runs once.

Can I see what Slack sends?

Put a Webhook Toolkit URL as the Request URL: the inspector shows the raw form body and both headers. To answer the challenge from your own code, use the Relay tunnel.

Other webhook guides

Oferta de lançamento · −50 %

Depurando uma integração de webhook esta semana?

O Pass 7 dias desbloqueia as explicações com IA e o código do handler pronto para colar, 25 URLs permanentes, 30 dias de histórico e o túnel Relay para localhost. Um único pagamento, sem assinatura.

€ 5 € 2,50 uma vez
Pagamento único · sem assinatura · reembolso em 14 dias · preço de lançamento até 30 de novembro
Slack X-Slack-Signature verification failing — signing secret, raw body, timestamp