La dirección de un webhook es como una puerta. Cualquiera que conozca la dirección puede enviarle una solicitud. Si no verifica la dirección a la que Meta envía los eventos de mensajes, cuando alguien envíe un evento falso que diga «el cliente hizo un pedido» o «pago confirmado», su flujo lo considerará real. Meta añade una firma a cada solicitud precisamente por esto. En este artículo explicamos qué es esa firma y cómo comprobarla en n8n. Apenas hemos encontrado este tema en fuentes en turco; por lo general solo se explica el paso de verificación de la configuración inicial y se omite la parte de la firma.
Respuesta corta
Meta añade un encabezado X-Hub-Signature-256 a cada solicitud POST. Este es el valor HMAC-SHA256 del cuerpo sin procesar de la solicitud, calculado con el secreto de su aplicación (app secret). Usted realiza el mismo cálculo en n8n y lo compara con el valor del encabezado; si no coinciden, descarta la solicitud sin procesarla. El error más frecuente es intentar calcular el hash sobre el JSON ya analizado.
Hay dos verificaciones distintas
Ambas se confunden con frecuencia. La primera ocurre al definir el webhook por primera vez: Meta envía una solicitud GET a su dirección que contiene hub.mode=subscribe, hub.verify_token y hub.challenge. verify_token es un texto que usted elige. Si el valor recibido coincide con el que ha guardado, devuelve el valor de hub.challenge con el código 200. Según la documentación de Meta, cualquier otra respuesta, incluidos los códigos 400, deja la dirección sin verificar y no llegará ningún webhook.
La segunda es la comprobación de firma que se ejecuta de forma continua, y es la que aporta la seguridad real. verify_token solo se solicita una vez, durante la configuración. Después, lo que verifica el origen de los eventos de mensajes entrantes es la firma.
¿Cómo se genera la firma?
El formato que describe Meta es este: el valor del encabezado X-Hub-Signature-256 comienza con «sha256=», seguido de un hash. Este hash es un HMAC-SHA256 calculado con el cuerpo de la solicitud y la clave secreta de su aplicación. Lo que usted debe hacer es realizar el mismo cálculo con el cuerpo recibido y su propia clave secreta, y comparar el resultado con la parte posterior a «sha256=» del encabezado. Si coinciden, la carga es válida, según la expresión de la documentación de Meta, y devuelve 200; si no coinciden, devuelve un código distinto de 200.
La clave secreta es el valor app secret que se encuentra en los ajustes de su aplicación en el panel de Meta for Developers. En lugar de escribirlo en texto plano dentro del workflow, es mejor guardarlo en el sistema de credenciales de n8n o en una variable de entorno.
¿Por qué es imprescindible el cuerpo sin procesar?
HMAC depende de los bytes exactos del cuerpo. La diferencia de un solo espacio o carácter de escape produce un hash completamente distinto. El nodo Webhook de n8n analiza automáticamente el JSON entrante; al volver a convertir el objeto analizado en texto, el orden de las claves, los espacios y la forma de escribir los caracteres especiales pueden cambiar. El resultado no coincidirá con el formato que usó Meta y hasta una solicitud legítima parecerá «inválida». Por esta misma razón hay un hilo en el foro de la comunidad de n8n que describe firmas que nunca coinciden: en el cuerpo sin procesar del remitente las barras estaban escapadas, mientras que en el cuerpo que muestra n8n no.
La solución es calcular el hash sobre los bytes sin procesar. El nodo Webhook de n8n tiene para ello la opción Raw Body. La documentación describe esta opción como que el nodo recibe los datos en formato sin procesar, como JSON o XML. Según un relato de la comunidad, al activar esta opción, además del cuerpo analizado, los bytes de la solicitud se conservan también como datos binarios. Como este comportamiento puede cambiar entre versiones, compruébelo en su propia configuración con una solicitud de prueba.
Configuración en n8n
El esqueleto del flujo es el siguiente:
- Nodo Webhook: Active la opción Raw Body. Si va a usar dos métodos distintos, definir rutas separadas para GET (verificación) y POST (eventos) simplifica el trabajo.
- Cálculo de la firma: Puede usar la operación Hmac del nodo Crypto. Según la documentación, se admite SHA256 y la salida puede ser HEX o BASE64. Como Meta envía el hash en hexadecimal, elija HEX y proporcione el cuerpo sin procesar como entrada. Si prefiere el nodo Code, necesita el módulo crypto de Node; por motivos de seguridad, n8n restringe el uso de módulos y exige el ajuste NODE_FUNCTION_ALLOW_BUILTIN=crypto. Si utiliza un Task Runner, este ajuste debe realizarse en el Task Runner, no en el nodo principal.
- Comparación: Elimine el prefijo "sha256=" del valor de la cabecera y compárelo con el hexadecimal calculado. Si es posible, utilice una comparación resistente a ataques de temporización; en el nodo Code, crypto.timingSafeEqual lo proporciona.
- Nodo If: Si la solicitud no coincide, detenga el flujo y devuelva un código de la serie 400 con Respond to Webhook. Si coincide, continúe.
De forma predeterminada, el nodo Webhook responde de inmediato con "Workflow got started". Si desea devolver códigos distintos según el resultado de la firma, debe cambiar el modo de respuesta al nodo Respond to Webhook.
¿Cuándo hay que devolver 200 a Meta?
Según Meta, las entregas fallidas se reintentan de inmediato y después con frecuencia decreciente durante 7 días. Es decir, si su flujo es lento o devuelve errores, el mismo mensaje puede llegarle muchas veces. Dos medidas funcionan. La primera: verificar la firma y devolver 200 de inmediato, dejando las tareas largas para después. La segunda: guardar el identificador de cada mensaje en una tabla y omitir los ya procesados. Meta también indica que las solicitudes pueden llegar agrupadas, que una sola solicitud puede contener hasta 1000 actualizaciones y que esto no está garantizado; procese cada solicitud por separado y mediante un bucle.
Capas adicionales
Aunque la verificación de la firma es suficiente, hay elementos que se pueden añadir además. Meta también documenta la compatibilidad con TLS mutuo (mTLS) para webhooks; debe activarse por separado para cada aplicación. En n8n, el nodo Webhook tiene una opción de lista de IP permitidas y las solicitudes externas reciben un 403, pero para que funcione debe mantener actualizadas las direcciones que usa Meta, y la lista de direcciones puede cambiar. Por eso, úsela junto a la firma, no en su lugar. El punto de conexión debe tener un certificado TLS válido; Meta no admite certificados autofirmados.
La elección del alojamiento también influye aquí. Con n8n en su propio servidor, usted gestiona las variables de entorno, la configuración del proxy inverso y el certificado; en la nube, una parte queda en manos del proveedor. Para una comparación, puede consultar nuestro artículo sobre costes de self-hosted y cloud. Dónde se almacenan los datos de clientes que llegan desde el webhook es otro tema aparte: lo tratamos en el artículo sobre automatización conforme a KVKK.
Una forma práctica de probar
Primero configúrelo con la URL de prueba, compruebe que se calcula el hash correcto y después pase a la URL de producción. Según la documentación de n8n, el webhook de prueba solo está registrado mientras está en modo de escucha, mientras que la dirección de producción se registra cuando se publica el workflow. Si en el panel de Meta está definida la dirección de producción, el flujo en modo de prueba no verá nada. Después utilice a propósito una clave secreta incorrecta y compruebe que la firma se rechaza. Una verificación cuyo lado de rechazo no se ha probado no ha demostrado que funcione.
Conviene que esta base sea sólida antes de montar flujos más avanzados, como vincular a las ventas los mensajes procedentes de anuncios; la parte publicitaria la explicamos en el artículo sobre ctwa_clid.
Preguntas frecuentes
¿Es obligatorio verificar la firma del webhook de WhatsApp?
La documentación de Meta indica que debe verificar la firma y, si es válida, devolver 200. Si no la verifica, cualquiera que conozca la dirección de su webhook puede enviar un evento de mensaje falso, y su flujo lo tomará por un mensaje real de un cliente.
¿Por qué no puedo calcular la firma a partir del JSON ya analizado?
El HMAC se calcula sobre los bytes exactos del cuerpo. Al analizar el JSON y volver a escribirlo, pueden cambiar los espacios, los caracteres de escape y el orden de los campos, y el hash no coincidirá. Por eso hay que trabajar con el cuerpo sin procesar.
¿Qué ocurre si Meta envía el mismo evento más de una vez?
Meta reintenta las entregas fallidas de inmediato y después con frecuencia decreciente durante 7 días. Por eso su flujo no debe procesar por segunda vez el mismo identificador de mensaje.
Fuentes: Meta for Developers, "Create a webhook endpoint" · n8n Docs, Webhook node · n8n Docs, Crypto node · n8n Docs, Modules in the Code node · n8n Community, ejemplo de verificación HMAC · n8n Community, problema del cuerpo sin procesar. La interfaz y el comportamiento pueden variar según la versión; pruebe en su propia instalación.
Revisemos juntos la seguridad de su flujo de webhook
Revisemos en media hora la verificación de firmas, los eventos duplicados y la gestión de errores en su flujo de WhatsApp.