Espero que alguien pueda decirme qué estoy haciendo mal aquí.
He configurado un Webhook de Discourse y funciona como se esperaba sin un Secreto. Luego escribo una cadena en el Secreto, y luego copio esa cadena en el Webhook receptor como una Cabecera, así:
X-Discourse-Event-Signature: secret_here
Esto produce el siguiente error en el Cuerpo cuando se envía el webhook de envío:
{"code":"rest_forbidden","message":"Lo siento, no tienes permiso para hacer eso.","data":{"status":401}}
Espero que simplemente no lo esté haciendo bien, ¡así que por favor ilumínenme!
Soy consciente de que el secreto se cifra utilizando sha256, por lo que la Cabecera que se envía es:
X-Discourse-Event-Signature: sha256=XXX
Pero no estoy seguro de qué debo hacer con esta información en las Cabeceras de Seguridad del Webhook receptor.
No estoy seguro si es solo la forma en que estás escribiendo la publicación, pero el encabezado real sería
X-Discourse-Event-Signature: XXX
Puedes usar (opcionalmente) esto en el extremo receptor para validar que el webhook fue enviado realmente por Discourse. Si no haces la verificación, una parte maliciosa podría potencialmente falsificar eventos de webhook.
Mi sitio web de Wordpress. Estoy usando un plugin de Wordpress para recibir Webhooks. Si no agrego un encabezado de seguridad (secreto), el Webhook funciona bien. El problema ocurre solo cuando agrego el secreto.
Las cabeceras de seguridad personalizadas pueden incluirse en el disparador de webhook entrante, pero una nota importante es cómo WordPress puede cambiar los guiones por guiones bajos. Por ejemplo, intentar usar “x-api-key” puede requerir usar “x_api_key” en su lugar.
Sin embargo, tengo una pregunta relacionada, @RGJ. Digamos que mi secreto es “1234”. En el webhook receptor, ¿debería el valor de X-Discourse-Event-Signature ser:
Parece que el plugin de Wordpress que estás utilizando solo puede compararse con un valor de encabezado estático, no con una firma dinámica. Esto es algo específico de Discourse.
He descubierto que el valor sha cambia cada vez que se envía el webhook, por lo que poner el valor sha en el webhook receptor no funcionaría. Pensaría que tendría que ser el ejemplo n.º 1 y, como creo que estás sugiriendo (encabezado estático), ¿el plugin necesitaría decodificar el hash antes de generar la respuesta del encabezado?
En conclusión, no creo que pueda usar el X-Discourse-Event-Signature hasheado en este plugin, porque solo aceptará valores estáticos.
¿Es inseguro usar un webhook sin un secreto? Enviaría eventos de usuario desde mi Discourse a mi sitio web principal, usando una URL no obvia como main-site.com/wp-json/fol/fil/532563-5312534. También puedo agregar encabezados estáticos que deben coincidir en el hook receptor.
¿Podrías darme un ejemplo de una aplicación que pueda manejar un hmac que cambie dinámicamente?
El valor se calcula contra la carga útil del webhook, por lo que será diferente para cada solicitud.
Esa es una pregunta interesante. La única aplicación que conozco es el plugin WP Discourse, pero se configuró específicamente para manejar los webhooks de Discourse. Si la implementación de Discourse está impidiendo que las personas validen webhooks con secretos, tal vez eso deba investigarse.
Dejaré que otros respondan a eso.
Si te preocupa no validar el webhook, quizás el plugin Incoming Webhook Triggers tenga un hook de acción en su código de recepción de webhooks que se active antes de que se procesen los datos del webhook. Si lo tiene, debería ser posible escribir una función que se enganche a él, compruebe si los datos son para un webhook de Discourse y luego valide el secreto con algo como el código que enlacé en mi publicación anterior.
Tenía curiosidad, así que investigué un poco. No estoy seguro sobre las aplicaciones que están configuradas para manejar la recepción de una firma HMAC que cambia dinámicamente, pero autenticar solicitudes de webhook con una firma HMAC que se calcula contra la carga útil es una práctica bastante estándar para las aplicaciones que envían webhooks. Por ejemplo, GitHub, Stripe y Shopify utilizan este método.
También hay bastantes aplicaciones populares que utilizan el método del token secreto para autenticar webhooks. Por ejemplo (a partir de 2021) Mailchimp, Trello, Slack y Discord utilizan este enfoque. Parece que Slack todavía utiliza este método: Slack developer FAQ | Slack Developer Docs. Puedo ver cómo eso facilitaría las cosas para la aplicación que recibe el webhook.
Supongo que hay un equilibrio entre seguridad y conveniencia a la hora de decidir qué método utilizará la aplicación que envía. Mi preocupación con el método de firma HMAC de Discourse es que podría llevar a que las personas configuren webhooks sin claves secretas para evitar la dificultad de manejar las firmas HMAC cambiantes. Por ejemplo, hay algunas referencias en Meta para enviar webhooks de Discourse a Zapier sin mencionar cómo validar la firma en Zapier. (Aunque técnicamente debería ser posible validar las firmas en Zapier. No estoy configurado para probar eso en este momento).
Estoy totalmente de acuerdo con esto. Quizás esto es algo que los desarrolladores pueden explorar: un método más fácil y compatible de asegurar los datos de los webhooks.
Además, no estoy tan seguro de que Zapier sea capaz de validar la firma.
La función de secreto de webhook se implementa de acuerdo con esto:
Parece que el software que desea no admite esta función de comunicación de seguridad estándar, pero aún puede utilizar los webhooks de Discourse sin ella.
No hay planes para agregar una cabecera fija con un secreto compartido, ya que el valor de seguridad de eso es cuestionable. Sin embargo, si necesita esto, debería ser factible en un plugin.