> For the complete documentation index, see [llms.txt](https://documentation.themembers.dev.br/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.themembers.dev.br/webhooks/webhooks-do-checkout/seguranca.md).

# Segurança

## **🔐 Validação de Assinatura de Webhooks**

Para garantir a **autenticidade** e a **integridade** das notificações enviadas pelo nosso sistema, todos os webhooks são assinados utilizando um segredo compartilhado (*webhook secret*), que realiza a assinatura do payload via HMAC SHA-256.

#### **📌 Como funciona**

Cada requisição enviada contém:

* O **payload** (corpo da requisição)
* Um header HTTP:

```
X-Signature: {assinatura}
```

Essa assinatura é gerada aplicando um **HMAC SHA-256** sobre o payload bruto utilizando o *token de segurança* configurado:

![image.png](https://297705385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmbuonzfEbI223CTyjCzW%2Fuploads%2FopEA1BgcoUgyDJOGqG5x%2Fimage.webp?alt=media\&token=de115e4b-9ad2-43c0-9eea-72fb906fb1e3)

***

#### **🎯 Objetivo da validação**

O sistema receptor deve validar a assinatura para garantir:

* ✔️ Que o payload **não foi alterado** (integridade)
* ✔️ Que a requisição foi **enviada por um remetente confiável** (autenticidade)
* ✔️ Que a comunicação é **segura contra ataques de replay ou spoofing**

***

### **⚙️ Passo a passo para validação**

Ao receber o webhook, seu sistema deve:

1. **Ler o payload bruto da requisição**
   * Importante: não utilize payload já parseado (ex: JSON decodificado)
2. **Obter o header `X-Signature`**
3. **Gerar uma nova assinatura localmente**
   * Utilizando:
     * O payload bruto
     * O *secret* compartilhado
4. **Comparar as assinaturas**
   * Utilize comparação segura (*timing-safe comparison*)
5. **Rejeitar a requisição caso a assinatura seja inválida**
   * Retorne HTTP `403 Forbidden`

***

### **💻 Exemplo em PHP (Laravel)**

```php
$newPayload = json_encode(
  json_decode(trim($payload)),
  JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);

$expectedSignature = hash_hmac(
  'sha256',
  $webhookURL . ':' . $newPayload,
  $secret
);
```

### **💻 Exemplo em NodeJS**

```javascript
const normalizedPayload = JSON.stringify(JSON.parse(req.body.toString('utf8')));

const data = `${webhookUrl}:${normalizedPayload}`;
const receivedSignature = req.headers['x-signature'];

const expected = crypto
  .createHmac('sha256', secret)
  .update(data, 'utf8')
  .digest('hex');

if (expected.length !== receivedSignature.length) {
  return false;
}

return crypto.timingSafeEqual(
  Buffer.from(expected, 'utf8'),
  Buffer.from(receivedSignature, 'utf8'),
);
```

***

### ⚠️ Boas práticas (importante)

#### 1. Use sempre o payload bruto

Qualquer transformação (ex: `json_decode` → `json_encode`) pode invalidar a assinatura.

***

#### 2. Nunca use comparação simples (`===`)

Utilize sempre:

```
hash_equals()
```

***

#### 3. Proteja seu webhook secret

* Nunca exponha no frontend
* Armazene em variáveis de ambiente seguras

***

#### 4. Valide antes de processar

A validação da assinatura deve ser o **primeiro passo** antes de qualquer lógica de negócio
