Skip to main content
Qualquer pessoa com acesso à URL do seu webhook pode simular uma entrega. Por isso, a SocialSell assina cada requisição com HMAC-SHA256 usando o secret da sua assinatura — e você deve validar essa assinatura antes de processar qualquer payload.

O header de assinatura

Cada entrega inclui o header:
X-SocialSell-Signature: sha256=a1b2c3d4e5f6789...
O valor é sha256= seguido do HMAC-SHA256 do corpo bruto da requisição, usando o secret da assinatura como chave.

Como validar

Sempre use o corpo bruto (raw bytes) da requisição, não o JSON parseado. Re-serializar o JSON pode alterar a assinatura.
const crypto = require('crypto');
const express = require('express');
const app = express();

// Use express.raw() para receber o corpo como Buffer
app.post('/webhooks/socialsell', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-socialsell-signature'];
  const secret = process.env.SOCIALSELL_WEBHOOK_SECRET;

  if (!isValidSignature(req.body, signature, secret)) {
    return res.status(401).json({ error: 'Assinatura inválida' });
  }

  const event = JSON.parse(req.body);
  console.log('Evento recebido:', event.event);

  // processar evento...
  res.status(200).send('OK');
});

function isValidSignature(body, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');

  // timingSafeEqual previne timing attacks
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expected)
    );
  } catch {
    return false;
  }
}

Erros comuns de validação

ProblemaCausaSolução
Assinatura sempre inválidaCorpo sendo parseado antes da validaçãoUse o corpo bruto (raw buffer)
timingSafeEqual lançando erroStrings de tamanho diferenteConfirme que o secret está correto
Validação falhando em produçãosecret com espaços ou quebra de linhaVerifique a variável de ambiente com trim()
Funcionou local, falha em produçãoProxy modificando o corpoConfigure o proxy para não modificar o payload

Boas práticas de segurança

  • Sempre valide antes de processar — nunca confie no payload sem verificar a assinatura
  • Use timingSafeEqual — previne timing attacks onde um atacante mede o tempo de comparação para adivinhar a assinatura
  • Armazene o secret como variável de ambiente — nunca no código ou em repositórios
  • Rejeite com 401 — não com 200. Responder com sucesso a payloads inválidos pode confundir sistemas de monitoramento
  • Rotacione o secret se comprometido — delete a assinatura e crie uma nova com POST /v1/webhooks