Skip to main content
Este documento describe el proceso de verificación de la autenticidad de los webhooks enviados desde Kausanna utilizando el método de Hash-based Message Authentication Code (HMAC). El propósito es asegurar que los mensajes recibidos en el endpoint del servidor del cliente provienen realmente de Kausanna y no han sido alterados en tránsito.

Paso a Paso para la Verificación

Paso 1: Captura del Webhook

Cuando su servidor recibe un webhook de Kausanna, primero debe capturar el cuerpo del mensaje y los headers. Preste especial atención al header x-hmac-hash, ya que contiene el hash HMAC que Kausanna utiliza para asegurar el mensaje.

Paso 2: Preparación de la Cadena para el Hash

Concatene la ruta completa de la URL (sin incluir el dominio) y el cuerpo del mensaje recibido. Esta concatenación es la que se utilizará para generar el hash de verificación. Asegúrese de no alterar el orden ni el contenido del mensaje durante este proceso.

Paso 3: Generación del Hash HMAC

Usted ha recibido el secret key de Kausanna cuando configuró los webhooks. Esta clave secreta es necesaria para generar el hash HMAC. El campo secret en el objeto de configuración del webhook en Kausanna es la clave secreta compartida. No se puede volver a ver después de que se haya guardado.
Utilice la clave secreta compartida (proporcionada por Kausanna cuando configura los webhooks) para generar un nuevo hash HMAC. Este paso se realiza utilizando el mismo algoritmo de hash que Kausanna usa para generar el x-hmac-hash. Por ejemplo, si Kausanna utiliza SHA-256, debe usar SHA-256 en su servidor también.
import * as crypto from "crypto";

function generate_hmac(url: string, payload: string, secret: string): string {
  const urlWithoutDomain = url.replace(/https?:\/\//, "");
  const data = `${urlWithoutDomain}${payload}`;
  return crypto.createHmac("sha256", secret).update(data).digest("hex");
}
En este código, secret es su clave secreta compartida, url es la URL completa del webhook y payload es el cuerpo del mensaje recibido.

Paso 4: Comparación de Hashes

Compare el hash HMAC que generó en el paso 3 con el valor del header x-hmac-hash recibido en el webhook. Si los dos hashes son idénticos, puede confiar en que el webhook es auténtico y no ha sido modificado.
function verify_hmac(received_hmac: string, generated_hmac: string): boolean {
  return crypto.timingSafeEqual(
    Buffer.from(received_hmac, "utf8"),
    Buffer.from(generated_hmac, "utf8")
  );
}
Utilice received_hmac para el hash del header x-hmac-hash y generated_hmac para el hash que generó.

Paso 5: Procesamiento del Webhook

Si la verificación es exitosa, proceda con el procesamiento normal del webhook. Si los hashes no coinciden, rechace el webhook y registre el evento para una revisión más detallada.
Es recomendable registrar los intentos fallidos de verificación de webhooks, ya que pueden indicar intentos de manipulación o errores en la configuración.
Guarde su clave secreta en un lugar seguro y nunca la exponga públicamente. La seguridad de la verificación HMAC depende de la confidencialidad de esta clave.

Ejemplo de Verificación HMAC en Node.js

A continuación se muestra un ejemplo de cómo implementar la verificación HMAC en Node.js utilizando Express y el módulo crypto.
import express from "express";
import * as crypto from "crypto";

const app = express();

app.use(express.json());

app.post("/webhook", (req, res) => {
  const received_hmac = req.headers["x-hmac-hash"];
  const generated_hmac = generate_hmac(req.url, JSON.stringify(req.body), "your_secret");

  if (verify_hmac(received_hmac, generated_hmac)) {
    console.log("Webhook verified successfully");
    // Process the webhook
    res.status(200).send("Webhook verified successfully");
  } else {
    console.error("Webhook verification failed");
    // Reject the webhook
    res.status(403).send("Webhook verification failed");
  }
});

function generate_hmac(url: string, payload: string, secret: string): string {
  const urlWithoutDomain = url.replace(/https?:\/\//, "");
  const data = `${urlWithoutDomain}${payload}`;
  return crypto.createHmac("sha256", secret).update(data).digest("hex");
}

function verify_hmac(received_hmac: string, generated_hmac: string): boolean {
  return crypto.timingSafeEqual(
    Buffer.from(received_hmac, "utf8"),
    Buffer.from(generated_hmac, "utf8")
  );
}

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});
En este ejemplo, el servidor Express escucha en el puerto 3000 y verifica el hash HMAC de los webhooks recibidos. Asegúrese de reemplazar "your_secret" con su clave secreta compartida.

Vulnerabilidades y Consideraciones de Seguridad

Almacenamiento Seguro de la Clave Secreta

La clave secreta compartida es un componente crítico de la verificación HMAC. Debe almacenarse de forma segura y no debe exponerse públicamente. Si la clave secreta se ve comprometida, los atacantes pueden falsificar webhooks y realizar acciones no autorizadas en su sistema.

Protección contra Ataques de Tiempo

Al comparar los hashes HMAC, es importante utilizar una comparación segura en tiempo para evitar ataques de temporización. La función crypto.timingSafeEqual en Node.js proporciona una comparación segura en tiempo que evita la revelación de información a través de la sincronización de relojes. Este tipo de ataque puede ser utilizado para adivinar la clave secreta a través de la comparación de tiempos de respuesta.

Registro de Intentos Fallidos

Es recomendable registrar los intentos fallidos de verificación de webhooks, ya que pueden indicar intentos de manipulación o errores en la configuración. El registro de estos eventos puede ayudar a identificar y mitigar posibles amenazas de seguridad.

Rotación de Claves Secretas

Es una buena práctica rotar las claves secretas periódicamente para reducir el riesgo de exposición. Si sospecha que su clave secreta ha sido comprometida, debe cambiarla inmediatamente y actualizar la configuración de los webhooks en Kausanna.

¿Que hacer en caso de compromiso de la clave secreta?

Si sospecha que su clave secreta ha sido comprometida, debe cambiarla inmediatamente y actualizar la configuración de los webhooks en Kausanna. Además, es recomendable revisar los registros de intentos fallidos de verificación de webhooks para identificar posibles actividades maliciosas. Pasos:
  1. Cree un webhook con los eventos que desee recibir. Puede clonar un webhook existente.
  2. Copie la nueva clave secreta generada por Kausanna.
  3. Actualice la configuración de su servidor para utilizar la nueva clave secreta.
  4. Elimine el webhook comprometido, puede buscar por ID o por URL.