Como verificar que los webhooks son enviados por DEUNA
Cuando se integra con nuestra plataforma, es altamente recomendado verificar las firmas de los webhooks para asegurarse de que los eventos recibidos son enviados por nosotros y no por un tercero. Firmamos los eventos de webhook enviados a sus puntos finales incluyendo una firma en el encabezado llamado X-Deuna-Signature
de cada evento. Esto le permite verificar la autenticidad de los eventos.
Importancia de la Verificación de Firmas de Webhook
Para proteger su servidor de eventos de webhook no autorizados, recomendamos el uso de firmas de Código de Autenticación de Mensajes Basado en Hash (HMAC usando el algoritmo SHA256) para nuestros webhooks que lo admiten. Para los webhooks que admiten habilitar firmas HMAC, cada evento incluirá una firma calculada utilizando una clave HMAC secreta y el payload del webhook. Al verificar esta firma, puede confirmar que:
- El webhook fue enviado por nosotros.
- El payload no fue modificado durante la transmisión.
Cómo Verificar la Firma del Webhook?
- Recuperar la Firma: Extraiga el encabezado
X-Deuna-Signature
de la solicitud entrante del webhook. - Generar la Firma Esperada: Utilice la misma clave HMAC secreta (private API Key) y el payload del webhook para generar la firma esperada.
- Comparar Firmas: Compare la firma generada con la firma recibida. Si coinciden, el webhook es legítimo.
Advertencia: Para validar la firma, es necesario utilizar el raw body de la solicitud. Si estás usando un framework, asegúrate de que no manipule el raw body. Cualquier modificación en el raw body provocará que la validación falle.
Sugerencia: En el cuerpo de la notificación se encuentra el valor
signed_at
. Recomendamos verificar el tiempo transcurrido desde que se generó la firma hasta el momento actual, y según tus necesidades, realizar la validación correspondiente.
Código de Ejemplo para Verificar la Firma
Aquí hay ejemplos en varios lenguajes para ilustrar cómo verificar la firma HMAC SHA256:
Python
import hmac
import hashlib
import base64
import json
from django.http import HttpResponse
def validate_hmac_sha256_signature(secret, payload, signature):
secret_bytes = bytes(secret, 'utf-8')
payload_bytes = bytes(payload, 'utf-8')
h = hmac.new(secret_bytes, payload_bytes, hashlib.sha256)
expected_signature = base64.b64encode(h.digest()).decode('utf-8')
return hmac.compare_digest(signature, expected_signature)
# Example
secret = "<your-private-api-key>"
# Using Django
@csrf_exempt
def my_webhook_view(request):
payload = request.body
sig_header = request.META['X-Deuna-Signature']
if not validate_hmac_sha256_signature(secret, payload, sig_header):
print("Invalid signature")
return HttpResponse(status=403)
return HttpResponse(status=201)
JS (Node.js)
const express = require('express');
const app = express();
const crypto = require('crypto');
const secret = "<your-private-api-key>"
function verifySignature(secret, signature, payload) {
const hmac = crypto.createHmac('sha256', secret);
const computedSignature = hmac.update(payload, 'utf8').digest('base64');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(computedSignature));
}
// Match the raw body to content type application/json
app.post('/webhook', express.raw({ type: 'application/json' }), (request, response) => {
const sig = request.headers['x-deuna-signature'];
const event = request.body;
try {
const verified = verifySignature(secret, sig, event);
console.log('Verified:', verified);
} catch (err) {
console.error(err);
response.status(400).send(`Webhook Error: ${err.message}`);
}
response.json({ received: true });
});
app.listen(4242, () => console.log('Running on port 4242'));
}
Updated 9 days ago