Verificação da assinatura

Toda notificação que enviamos para o seu endpoint é assinada. Fazemos isso incluindo um header com o nome "Transfeera-Signature" em cada evento que enviamos. Isso permite verificar e garantir que o evento foi enviado pela Transfeera e não por um terceiro.

O Header "Transfeera-Signature" contêm um timestamp e uma ou mais assinaturas. O timestamp é prefixado por t= e cada assinatura é prefixado por um schema. Schemas começa com v seguido de um integer. Atualmente existe apenas um schema de assinatura que é o v1.

Exemplo do Header Transfeera-Signature:

Transfeera-Signature: t=1580306324381,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Assinaturas são geradas usando uma mensagem baseada em hash com código de autenticação (HMAC) com SHA-256. Para prevenir ataques de reversão de versão (downgrade attacks), você deve ignorar todos os schemas que não são v1.

Como validar a assinatura

Passo 1: Extrair o timestamp e assinatura do Header

Faça um split no header usando o caractere , como separador para pegar a lista de elementos. Feito isso, faça outro split usando o caractere = como separador, para pegar o prefixo e o valor.

O valor obtido no prefixo t corresponde ao timestamp e o v1 corresponde à assinatura. Você pode descartar outros valores.

Passo 2: Preparar a string para comparar as assinaturas

Você deve concatenar essas informações:

  • O timestamp (como string)
  • O caractere .
  • O raw payload JSON (corpo da requisição, em formato de string)

Computar o HMAC com a função hash SHA256. Use o secret recebido na hora da criação do webhook e use a string signed_payload como mensagem.

Exemplo em Node.JS:

const crypto = require('crypto');

const secretKey = 'my-secret'; // Essa secret não é a secret do token de autenticação, é a secret recebida na hora da criação do webhook através do POST /webhook
const ts = 1580306991086; // This is the "t" value received on Transfeera-Signature header
const requestPayload = '{"testing":true,"someString":"string-value"}';

const signed_payload = `${ts}.${requestPayload}`;

const signature = crypto
  .createHmac('sha256', secretKey)
  .update(signed_payload)
  .digest('hex');

console.log(signature);
// Output: 348a92ec7864e30fc9cf3ea91b2e6e1392a14c8379103cb1d8e48e39334a4fd8

📘

O payload JSON deve ser mantido exatamente como foi recebido, sem qualquer conversão ou formatação. Qualquer alteração, como transformá-lo em um objeto e depois reconvertê-lo em string (por exemplo, usando JSON.stringify), pode resultar em diferenças que invalidariam a assinatura calculada.

Passo 3: Comparar as assinaturas

Compare a assinatura enviada pela Transfeera no Header com a assinatura que você gerou no Passo 2.

Exemplo em Node.JS:

// Comparando assinaturas
// Exemplo do Header da requisição enviada pela Transfeera:
const requestHeaders = {
  'Transfeera-Signature': 't=1580306991086,v1=348a92ec7864e30fc9cf3ea91b2e6e1392a14c8379103cb1d8e48e39334a4fd8'
}

// Extraia o valor de 't' do Header 'Transfeera-Signature'
const reqTimestamp = requestHeaders['Transfeera-Signature'].split(',')[0].split('=')[1]; // '1580306991086'

// Extraia o valor de 'v1' do Header 'Transfeera-Signature'
const reqSignature = requestHeaders['Transfeera-Signature'].split(',')[1].split('=')[1]; // '348a92ec7864e30fc9cf3ea91b2e6e1392a14c8379103cb1d8e48e39334a4fd8'

// A Assinatura que você gerou no Passo 2 deve ser igual ao valor da variável "reqSignature".
console.log('yourSignature' === reqSignature); // Deve retornar verdadeiro