Como verificar assinaturas de webhook do Zendesk: Um guia completo para desenvolvedores

Stevia Putri
Escrito por

Stevia Putri

Última edição March 2, 2026

Verificado por especialista
Imagem do banner para Como verificar assinaturas de webhook do Zendesk: Um guia completo para desenvolvedores

Quando você cria integrações que recebem webhooks do Zendesk, você abre um endpoint no seu servidor que aceita requisições HTTP da internet. Sem a verificação adequada, qualquer pessoa poderia enviar requisições falsas para esse endpoint e potencialmente acionar ações indesejadas no seu sistema. É aí que entra a verificação de assinatura.

A verificação de assinatura de webhook do Zendesk oferece uma maneira de provar criptograficamente que os webhooks recebidos realmente vieram do Zendesk e não foram adulterados em trânsito. Este guia orienta você em tudo que você precisa para implementá-lo corretamente, com exemplos de código funcional em cinco linguagens de programação populares.

Se você está procurando uma orientação mais ampla sobre como configurar webhooks no Zendesk, nosso guia de configuração de webhooks de mensagens do Zendesk cobre o processo de configuração completo.

Painel de simulação de eesel AI mostrando taxas de automação previstas para uma integração Zendesk ChatGPT
Painel de simulação de eesel AI mostrando taxas de automação previstas para uma integração Zendesk ChatGPT

O que é a verificação de assinatura de webhook e por que ela é importante

A verificação de assinatura de webhook é um mecanismo de segurança que permite confirmar a autenticidade das requisições de webhook recebidas. Quando o Zendesk envia um webhook para seu endpoint, ele inclui uma assinatura criptográfica que somente o Zendesk poderia ter gerado. Seu servidor recalcula essa assinatura usando um segredo compartilhado e compara os resultados. Se eles corresponderem, o webhook é genuíno.

Sem essa verificação, seu endpoint fica vulnerável a vários ataques:

  • Spoofing: Qualquer pessoa que descobrir seu URL de webhook pode enviar requisições falsas fingindo ser o Zendesk
  • Ataques de replay: Um invasor pode capturar um webhook legítimo e reenviá-lo várias vezes
  • Adulteração de payload: Os dados da requisição podem ser modificados em trânsito sem detecção

Para integrações de produção que lidam com dados confidenciais de tickets ou acionam fluxos de trabalho automatizados, a verificação de assinatura não é opcional. É um controle de segurança fundamental que protege tanto seu sistema quanto os dados de seus clientes.

Na eesel AI, lidamos com a segurança de webhook automaticamente quando você conecta sua conta Zendesk. Nossa plataforma verifica as assinaturas de forma transparente para que você possa se concentrar na criação de automações em vez de implementações criptográficas.

Como funcionam as assinaturas de webhook do Zendesk

O Zendesk usa o algoritmo SHA256 HMAC (Hash-based Message Authentication Code) para gerar assinaturas de webhook. O processo combina o segredo de assinatura do seu webhook com o payload da requisição e o timestamp para criar uma assinatura exclusiva para cada requisição.

A fórmula se parece com isto:

base64(HMACSHA256(TIMESTAMP + BODY))

Veja o que acontece quando o Zendesk envia um webhook:

  1. O Zendesk concatena o timestamp e o corpo da requisição bruto em uma única string
  2. Ele cria um hash HMAC-SHA256 usando o segredo de assinatura do seu webhook como chave
  3. O hash é codificado em Base64 para produzir a assinatura final
  4. O Zendesk envia o webhook com dois cabeçalhos críticos:
    • X-Zendesk-Webhook-Signature - a assinatura gerada
    • X-Zendesk-Webhook-Signature-Timestamp - o timestamp usado na assinatura

Cada requisição de webhook do Zendesk inclui estes cabeçalhos padrão:

x-zendesk-account-id: 123456 x-zendesk-webhook-id: 01F1KRFQ6BG29CNWFR60NK5FNY x-zendesk-webhook-invocation-id: 8350205582 x-zendesk-webhook-signature: EiqWE3SXTPQpPulBV6OSuuGziIishZNc1VwNZYqZrHU= x-zendesk-webhook-signature-timestamp: 2021-03-25T05:09:27Z

No seu servidor, você extrai esses cabeçalhos, recalcula a assinatura usando seu segredo de assinatura armazenado e compara os resultados. Se as assinaturas corresponderem, você pode confiar que o webhook veio do Zendesk e que o payload não foi modificado.

Fluxo de verificação de assinatura de webhook do Zendesk para seu servidor
Fluxo de verificação de assinatura de webhook do Zendesk para seu servidor

Recuperando seu segredo de assinatura de webhook

Antes de poder verificar as assinaturas, você precisa do segredo de assinatura do seu webhook. Cada webhook no Zendesk tem seu próprio segredo exclusivo que é gerado quando o webhook é criado.

Encontrando seu segredo no Admin Center

  1. Navegue até o Admin Center do Zendesk (Admin Center > Apps and integrations > Webhooks)
  2. Selecione o webhook que você deseja verificar
  3. Na página de detalhes do webhook, procure o campo de segredo de assinatura
  4. Clique em "Reveal secret" (Revelar segredo) para exibir o valor
Interface de configuração de webhook do Zendesk mostrando métodos de conexão
Interface de configuração de webhook do Zendesk mostrando métodos de conexão

Trate este segredo como qualquer outra credencial. Não o coloque no código, não o exponha em aplicações do lado do cliente e restrinja o acesso a ele dentro de sua equipe.

Recuperando via API

Você também pode buscar o segredo de assinatura programaticamente usando a API Show webhook signing secret:

GET /api/v2/webhooks/{webhook_id}/signing_secret

Segredo de teste estático para desenvolvimento

Quando você estiver testando webhooks antes de criá-los no Zendesk, você precisará de um segredo de assinatura estático, pois os segredos reais só são gerados após a criação do webhook. Use este segredo de teste durante o desenvolvimento:

dGhpc19zZWNyZXRfaXNfZm9yX3Rlc3Rpbmdfb25seQ==

Depois que seu webhook for criado, mude para o segredo de assinatura real. Webhooks de teste e webhooks ativos usam segredos diferentes, então seu código de verificação precisa lidar com o segredo correto para cada ambiente.

Captura de tela da página inicial do Zendesk
Captura de tela da página inicial do Zendesk

Guia de implementação passo a passo

A implementação da verificação de assinatura envolve quatro etapas principais. Vamos detalhar cada uma delas.

Passo 1: Capture o corpo da requisição bruto

A assinatura é calculada no corpo da requisição bruto como uma string, não em JSON analisado ou dados de formulário. Se sua estrutura analisa o corpo antes que você possa acessá-lo, a verificação da assinatura falhará porque os bytes brutos foram transformados.

A maioria das estruturas da web fornece middleware ou opções de configuração para capturar o corpo bruto antes da análise. Normalmente, você precisa armazenar o corpo bruto em uma propriedade como req.rawBody para que ele esteja disponível para o cálculo da assinatura.

Armadilha comum: O middleware de análise de corpo (como express.json() do Express) geralmente é executado antes do seu manipulador de rota. Se o corpo for analisado em um objeto JavaScript antes de você capturar a string bruta, você não poderá recuperar os bytes originais para a verificação da assinatura. Configure seu middleware para capturar o corpo bruto primeiro.

Passo 2: Extraia os cabeçalhos de assinatura

Extraia os dois cabeçalhos relacionados à assinatura da requisição recebida:

  • X-Zendesk-Webhook-Signature - a assinatura para verificar
  • X-Zendesk-Webhook-Signature-Timestamp - o timestamp usado no cálculo da assinatura

Observe que algumas estruturas transformam os nomes dos cabeçalhos. No Ruby on Rails, por exemplo, o cabeçalho X-Zendesk-Webhook-Signature se torna HTTP_X_ZENDESK_WEBHOOK_SIGNATURE no ambiente de requisição.

Passo 3: Calcule a assinatura esperada

Concatene o timestamp e o corpo bruto e, em seguida, crie um hash HMAC-SHA256 usando seu segredo de assinatura:

  1. Crie uma string: timestamp + body (timestamp primeiro, depois o corpo bruto)
  2. Gere HMAC-SHA256 usando seu segredo de assinatura como chave
  3. Codifique o hash resultante em Base64

Esta assinatura calculada deve corresponder àquela que o Zendesk enviou no cabeçalho X-Zendesk-Webhook-Signature.

Passo 4: Compare as assinaturas com segurança

Use uma função de comparação de tempo constante para comparar as assinaturas. A comparação de string regular (== ou ===) pode vazar informações sobre a assinatura por meio da análise de tempo, o que poderia teoricamente ajudar um invasor a forjar assinaturas válidas.

A maioria das linguagens fornece uma função de comparação de tempo constante:

  • Node.js: crypto.timingSafeEqual()
  • Python: hmac.compare_digest()
  • PHP: hash_equals()
  • Ruby: ActiveSupport::SecurityUtils.secure_compare()
  • C#: Nenhuma comparação de tempo constante integrada, mas CryptographicOperations.FixedTimeEquals() no .NET Core

Se as assinaturas corresponderem, processe o webhook. Se elas não corresponderem, retorne uma resposta 401 Unauthorized e registre a falha para investigação.

Exemplos de código em linguagens populares

Aqui estão implementações completas e funcionais para as linguagens de desenvolvimento web mais comuns.

Node.js/Express

const express = require('express'); const crypto = require('crypto'); const SIGNING_SECRET = 'your_webhook_signing_secret_here'; const PORT = 3000; const app = express(); // Middleware para capturar o corpo bruto function storeRawBody(req, res, buf) { if (buf && buf.length) { req.rawBody = buf.toString('utf8'); } } app.use(express.json({ verify: storeRawBody })); app.use(express.urlencoded({ verify: storeRawBody, extended: true })); function isValidSignature(signature, body, timestamp) { const hmac = crypto.createHmac('sha256', SIGNING_SECRET); const sig = hmac.update(timestamp + body).digest('base64'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(sig) ); } app.post('/webhook', (req, res) => { const signature = req.headers['x-zendesk-webhook-signature']; const timestamp = req.headers['x-zendesk-webhook-signature-timestamp']; const body = req.rawBody; if (!isValidSignature(signature, body, timestamp)) { console.log('Invalid webhook signature'); return res.status(401).send('Unauthorized'); } // Processar o webhook verificado console.log('Webhook verified, processing...'); res.status(200).send('OK'); }); app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Python (Flask)

from flask import Flask, request, abort import hmac import hashlib import base64 app = Flask(__name__) SIGNING_SECRET = b'your_webhook_signing_secret_here' @app.route('/webhook', methods=['POST']) def handle_webhook(): # Obter o corpo bruto raw_body = request.get_data() # Extrair cabeçalhos signature = request.headers.get('X-Zendesk-Webhook-Signature', '') timestamp = request.headers.get('X-Zendesk-Webhook-Signature-Timestamp', '') # Calcular a assinatura esperada signed_payload = (timestamp + raw_body.decode('utf-8')).encode('utf-8') expected_signature = base64.b64encode( hmac.new(SIGNING_SECRET, signed_payload, hashlib.sha256).digest() ).decode('utf-8') # Verificar a assinatura if not hmac.compare_digest(expected_signature, signature): abort(401) # Processar o webhook verificado return '', 200 if __name__ == '__main__': app.run(port=3000)

PHP

<?php define('SIGNING_SECRET', 'your_webhook_signing_secret_here'); function verify_webhook($body, $signature, $timestamp) { // Concatenar timestamp e corpo $signed_payload = $timestamp . $body; // Calcular HMAC (saída binária) $calculated_hmac = base64_encode( hash_hmac('sha256', $signed_payload, SIGNING_SECRET, true) ); // Comparação de tempo constante return hash_equals($signature, $calculated_hmac); } // Lidar com a requisição de webhook $signature = $_SERVER['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE'] ?? ''; $timestamp = $_SERVER['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE_TIMESTAMP'] ?? ''; $body = file_get_contents('php://input'); if (!verify_webhook($body, $signature, $timestamp)) { http_response_code(401); exit('Unauthorized'); } // Processar o webhook verificado http_response_code(200); echo 'OK';

Ruby on Rails

class WebhooksController < ApplicationController skip_before_action :verify_authenticity_token SIGNING_SECRET = ENV['ZENDESK_WEBHOOK_SECRET'] def zendesk signature = request.headers['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE'] timestamp = request.headers['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE_TIMESTAMP'] body = request.body.read # Calcular a assinatura signed_payload = timestamp + body expected_signature = Base64.strict_encode64( OpenSSL::HMAC.digest('SHA256', SIGNING_SECRET, signed_payload) ) # Verificar unless ActiveSupport::SecurityUtils.secure_compare(expected_signature, signature) head :unauthorized return end # Processar webhook head :ok end end

C#

using System; using System.IO; using System.Security.Cryptography; using System.Text; using Microsoft.AspNetCore.Mvc; [ApiController] [Route("webhook")] public class WebhookController : ControllerBase { private const string SigningSecret = "your_webhook_signing_secret_here"; [HttpPost] public IActionResult HandleWebhook() { string signature = Request.Headers["X-Zendesk-Webhook-Signature"]; string timestamp = Request.Headers["X-Zendesk-Webhook-Signature-Timestamp"]; // Ler o corpo bruto using var reader = new StreamReader(Request.Body); string body = reader.ReadToEnd(); // Calcular a assinatura string signedPayload = timestamp + body; byte[] keyBytes = Encoding.UTF8.GetBytes(SigningSecret); byte[] payloadBytes = Encoding.UTF8.GetBytes(signedPayload); using var hmac = new HMACSHA256(keyBytes); byte[] hash = hmac.ComputeHash(payloadBytes); string expectedSignature = Convert.ToBase64String(hash); // Comparar (insensível a maiúsculas e minúsculas para compatibilidade) if (!signature.Equals(expectedSignature, StringComparison.OrdinalIgnoreCase)) { return Unauthorized(); } return Ok(); } }

Problemas comuns e solução de problemas

Mesmo com o código certo, a verificação da assinatura pode falhar por motivos sutis. Aqui estão os problemas mais comuns que os desenvolvedores encontram.

Espaçamento e formatação JSON

Um dos problemas mais frustrantes envolve a formatação JSON. A assinatura é calculada nos bytes exatos que o Zendesk envia, incluindo espaços em branco. Se sua estrutura reformatar o JSON (adicionando ou removendo espaços), a assinatura não corresponderá.

Um desenvolvedor na comunidade Zendesk descobriu isso da maneira mais difícil:

Descobri. Tinha a ver com o espaçamento na requisição json. O payload json deve ter um espaço antes e depois de ':' e nenhum outro espaço ou tabulação em qualquer outro lugar.

A solução é sempre verificar a assinatura em relação ao corpo da requisição bruto antes que qualquer análise ou transformação ocorra.

Diferenças entre webhook de teste e webhook ativo

Outro problema comum envolve diferenças entre o recurso de webhook de teste do Zendesk e as invocações de webhook ao vivo. O formato do payload pode variar ligeiramente entre os dois, fazendo com que as assinaturas sejam validadas em testes, mas falhem em produção.

Percebi que quando o webhook é executado normalmente, a autenticação da mensagem falha. Então, copiei o corpo da tentativa fracassada, voltei para 'Test Webhook' (Testar Webhook), colei o conteúdo no corpo da mensagem, enviei e a validação da mensagem agora funciona novamente.

Sempre teste com invocações de webhook reais de eventos reais do Zendesk antes de implantar em produção.

Codificação de caracteres

Certifique-se de que o timestamp e o corpo sejam tratados como strings UTF-8 ao concatenar para o cálculo da assinatura. Incompatibilidades de codificação entre seu servidor e o payload do Zendesk causarão falhas de verificação.

Validação de timestamp

Considere adicionar a validação de timestamp para evitar ataques de replay. Verifique se o timestamp no cabeçalho está dentro de uma janela razoável (por exemplo, 5 minutos) da hora atual. Timestamps antigos podem indicar um ataque de replay.

Quando regenerar segredos

Se você suspeitar que seu segredo de assinatura foi comprometido, regenere-o imediatamente através do Admin Center do Zendesk. Após a regeneração, atualize seu servidor com o novo segredo. Pode haver uma breve janela onde os webhooks em trânsito usam o segredo antigo, então considere suportar ambos durante a transição.

Testando sua verificação de webhook

Antes de implantar em produção, teste completamente sua implementação de verificação de assinatura.

Usando o segredo de teste estático

Durante o desenvolvimento, use o segredo de teste estático do Zendesk (dGhpc19zZWNyZXRfaXNfZm9yX3Rlc3Rpbmdfb25seQ==) para verificar se sua lógica de implementação está correta. Isso permite que você teste sem criar um webhook ativo.

Testando com o recurso de teste do Zendesk

Quando você cria ou edita um webhook no Zendesk, use o botão "Test Webhook" (Testar Webhook) para enviar payloads de teste. Verifique se seu endpoint aceita essas requisições e valida a assinatura corretamente.

Teste ao vivo

Crie um gatilho real que invoque seu webhook em um evento específico (como a criação de um ticket). Execute essa ação no Zendesk e confirme se seu endpoint recebe e verifica o webhook. Verifique os logs do seu servidor para quaisquer incompatibilidades de assinatura.

Registro e depuração

Registre as seguintes informações durante o desenvolvimento para ajudar a depurar falhas:

  • Corpo da requisição bruto (antes da análise)
  • Cabeçalho de assinatura recebido
  • Assinatura calculada
  • Cabeçalho de timestamp

Nunca registre o segredo de assinatura em si. Compare as assinaturas recebidas e calculadas caractere por caractere para identificar onde elas divergem.

Fluxo de trabalho de teste sistemático para verificação de assinatura de webhook
Fluxo de trabalho de teste sistemático para verificação de assinatura de webhook

Proteja suas integrações Zendesk com eesel AI

Implementar a verificação de assinatura de webhook corretamente requer atenção cuidadosa aos detalhes criptográficos, ao tratamento de corpo específico da estrutura e aos casos extremos em torno da formatação JSON. Para equipes que criam integrações complexas, essa complexidade pode retardar o desenvolvimento e introduzir riscos de segurança.

Na eesel AI, construímos a segurança de webhook diretamente em nossa integração Zendesk. Quando você conecta sua conta Zendesk à nossa plataforma, lidamos com a verificação de assinatura automaticamente. Você obtém os benefícios de segurança sem escrever e manter o código de verificação.

Painel de eesel AI para configurar o agente supervisor com interface sem código
Painel de eesel AI para configurar o agente supervisor com interface sem código

Nosso AI Agent para Zendesk vai além, fornecendo resolução autônoma de tickets enquanto lida com toda a segurança de webhook nos bastidores. Se você está criando automações baseadas em webhook e deseja se concentrar na lógica de negócios em vez de implementações criptográficas, podemos ajudar a simplificar sua integração.

Perguntas Frequentes

Sim, você precisa de acesso de administrador ao Admin Center do Zendesk para visualizar ou regenerar os segredos de assinatura de webhook. Os segredos são ocultados por padrão e exigem que você clique em 'Reveal secret' (Revelar segredo) para exibir.
Não, cada webhook tem seu próprio segredo de assinatura exclusivo gerado quando é criado. Você não pode compartilhar segredos entre webhooks e tentar verificar o payload de um webhook com o segredo de outro webhook sempre falhará.
Primeiro, verifique se você está usando o segredo de assinatura correto (não o segredo de teste estático para webhooks ativos). Verifique se você está capturando o corpo da requisição bruto antes de qualquer análise JSON. Certifique-se de que sua concatenação de timestamp e corpo corresponda exatamente ao formato do Zendesk. Finalmente, verifique se não há problemas de codificação com o payload.
Embora não seja estritamente necessária, a verificação de assinatura é fortemente recomendada para qualquer integração de produção. Sem ela, seu endpoint fica vulnerável a ataques de spoofing e replay. O Zendesk inclui os cabeçalhos de assinatura em todos os webhooks, então não há desvantagem em verificá-los.
Rotacione seus segredos de assinatura sempre que suspeitar de comprometimento, quando membros da equipe com acesso saírem ou como parte de uma auditoria de segurança regular (trimestral ou anualmente). Lembre-se de que rotacionar um segredo exige a atualização imediata do seu código de verificação, pois novos webhooks usarão o novo segredo.
Não, o segredo de teste estático só funciona com o recurso 'Test Webhook' (Testar Webhook) do Zendesk durante a criação do webhook. Depois que um webhook é criado, ele recebe seu próprio segredo de assinatura exclusivo que você deve usar para verificação.
Qualquer linguagem que suporte hashing HMAC-SHA256 e codificação Base64 pode verificar webhooks do Zendesk. As implementações mais comuns usam Node.js, Python, PHP, Ruby, Java, C# e Go. As operações criptográficas são padrão e estão disponíveis na maioria das bibliotecas padrão de linguagem.

Share this article

Stevia Putri

Article by

Stevia Putri

Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.

Pronto para contratar seu colega de IA?

Configure em minutos. Sem cartão de crédito necessário.

Comece grátis