Validar solicitudes de HubSpot

Para garantizar que las solicitudes que tu integración recibe de HubSpot realmente provengan de HubSpot, hay dos encabezados en la solicitud. Puedes usar estos encabezados, junto con los campos de la solicitud entrante, para verificar la firma de la solicitud.

El método utilizado para verificar la firma depende de la versión de la firma:

  • Para validar una solicitud usando la última versión de la firma de HubSpot, usa el encabezado X-HubSpot-Signature-V3 y sigue las instrucciones asociadas para validar la versión v3 de la firma.
  • Para la compatibilidad con versiones anteriores, las solicitudes de HubSpot también incluyen versiones anteriores de la firma. Para validar una versión anterior de la firma, verifica el encabezado X-HubSpot-Signature-Version , y luego sigue las instrucciones asociadas a continuación según si la versión es v1 o v2.

En las siguientes instrucciones, descubre cómo obtener un valor del hash del secreto del cliente de tu aplicación y los campos de una solicitud entrante. Una vez que calcules el valor del hash, lo compararás con la firma. Si los dos son iguales, entonces la solicitud pasó la validación. De lo contrario, la solicitud puede haber sido manipulada en tránsito o alguien puede estar falsificando solicitudes en tu punto de terminación.

Validar solicitudes usando la firma de solicitud v1

Si tu aplicación está suscrita a eventos de objetos del CRM a través de la API de webhooks, las solicitudes de HubSpot se enviarán con el encabezado X-HubSpot-Signature-Version establecido en v1. El encabezado X-HubSpot-Signature será un hash SHA-256 creado usando el secreto del cliente de tu aplicación junto con detalles de la solicitud.

Para verificar esta versión de la firma, realiza los siguientes pasos:

  • Crea una cadena que concatene lo siguiente: Client secret request body (si está presente)
  • Crea un hash SHA-256 de la cadena resultante.
  • Compara el valor del hash con el valor del encabezado X-HubSpot-Signature.
    • Si son iguales, esta solicitud ha superado la validación.
    • Si estos valores no coinciden, es posible que esta solicitud haya sido manipulada en tránsito o que alguien esté falsificando solicitudes a tu punto final.

Ejemplo para una solicitud con un cuerpo:

//Client secret : yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy // Request body: [ {"eventId":1,"subscriptionId":12345," portalId":62515", occurredAt":1564113600000", subscriptionType":"contact.creation", "attemptNumber":0, "objectId":123, "changeSource":"CRM", "changeFlag":"NEW", "appId":54321} ]

Ejemplos de firma de solicitud v1: 

NOTE: This is only an example for generating the expected hash. You will need to compare this expected hash with the actual hash in the X-HubSpot-Signature header. >>> import hashlib >>> client_secret = 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' >>> request_body = '[{"eventId":1,"subscriptionId":12345,"portalId":62515,"occurredAt":1564113600000,"subscriptionType":"contact.creation","attemptNumber":0,"objectId":123,"changeSource":"CRM","changeFlag":"NEW","appId":54321}]' >>> source_string = client_secret + request_body >>> source_string 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy[{"eventId":1,"subscriptionId":12345,"portalId":62515,"occurredAt":1564113600000,"subscriptionType":"contact.creation","attemptNumber":0,"objectId":123,"changeSource":"CRM","changeFlag":"NEW","appId":54321}]' >>> hashlib.sha256(source_string).hexdigest() '232db2615f3d666fe21a8ec971ac7b5402d33b9a925784df3ca654d05f4817de' NOTE: This is only an example for generating the expected hash. You will need to compare this expected hash with the actual hash in the X-HubSpot-Signature header. irb(main):003:0> require 'digest' => true irb(main):004:0> client_secret = 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' => "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" irb(main):005:0> request_body = '[{"eventId":1,"subscriptionId":12345,"portalId":62515,"occurredAt":1564113600000,"subscriptionType":"contact.creation","attemptNumber":0,"objectId":123,"changeSource":"CRM","changeFlag":"NEW","appId":54321}]' => "[{\"eventId\":1,\"subscriptionId\":12345,\"portalId\":62515,\"occurredAt\":1564113600000,\"subscriptionType\":\"contact.creation\",\"attemptNumber\":0,\"objectId\":123,\"changeSource\":\"CRM\",\"changeFlag\":\"NEW\",\"appId\":54321}]" irb(main):006:0> source_string = client_secret + request_body => "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy[{\"eventId\":1,\"subscriptionId\":12345,\"portalId\":62515,\"occurredAt\":1564113600000,\"subscriptionType\":\"contact.creation\",\"attemptNumber\":0,\"objectId\":123,\"changeSource\":\"CRM\",\"changeFlag\":\"NEW\",\"appId\":54321}]" irb(main):007:0> Digest::SHA256.hexdigest source_string => "232db2615f3d666fe21a8ec971ac7b5402d33b9a925784df3ca654d05f4817de" NOTE: This is only an example for generating the expected hash. You will need to compare this expected hash with the actual hash in the X-HubSpot-Signature header. > const crypto = require('crypto') undefined > client_secret = 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' > request_body = '[{"eventId":1,"subscriptionId":12345,"portalId":62515,"occurredAt":1564113600000,"subscriptionType":"contact.creation","attemptNumber":0,"objectId":123,"changeSource":"CRM","changeFlag":"NEW","appId":54321}]' '[{"eventId":1,"subscriptionId":12345,"portalId":62515,"occurredAt":1564113600000,"subscriptionType":"contact.creation","attemptNumber":0,"objectId":123,"changeSource":"CRM","changeFlag":"NEW","appId":54321}]' > source_string = client_secret + request_body 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy[{"eventId":1,"subscriptionId":12345,"portalId":62515,"occurredAt":1564113600000,"subscriptionType":"contact.creation","attemptNumber":0,"objectId":123,"changeSource":"CRM","changeFlag":"NEW","appId":54321}]' > hash = crypto.createHash('sha256').update(source_string).digest('hex') '232db2615f3d666fe21a8ec971ac7b5402d33b9a925784df3ca654d05f4817de'

El hash resultante sería el siguiente:
232db2615f3d666fe21a8ec971ac7b5402d33b9a925784df3ca654d05f4817de

Validar solicitudes usando la firma de solicitud v2

Si tu aplicación está manejando datos de una acción de webhook en un workflow, o si estás devolviendo datos para una tarjeta del CRM personalizada, la solicitud de HubSpot se envía con el encabezado X-HubSpot-Signature-Version establecido en v2. El encabezado X-HubSpot-Signature será un hash SHA-256 creado usando el secreto del cliente de tu aplicación junto con detalles de la solicitud.

Para verificar esta firma, realiza los siguientes pasos:

  • Crea una cadena que concatene lo siguiente: Client secret + http method + URI + request body (si está presente)
  • Crea un hash SHA-256 de la cadena resultante.
  • Compara el valor del hash a la firma.
    • Si son iguales, esta solicitud ha superado la validación.
    • Si estos valores no coinciden, es posible que esta solicitud haya sido manipulada en tránsito o que alguien esté falsificando solicitudes a tu punto final.

Notas:
  • La URL utilizada para crear la cadena de origen debe coincidir exactamente con la solicitud original, incluyendo el protocolo. Si tienes problemas para validar la firma, asegúrate de que cualquier parámetro de consulta esté en el mismo orden que se enumeró en la solicitud original.
  • La cadena de origen debe tener codificación UTF-8 antes de calcular el hash SHA-256.

Ejemplo de una solicitud GET:


Ejemplo para una solicitud con un cuerpo:

 

Validar la firma de solicitud v3

El encabezado X-HubSpot-Signature será un hash SHA-256 creado usando el secreto del cliente de tu aplicación junto con detalles de la solicitud. También incluirá un encabezado X-HubSpot-Request-Timestamp.

Al validar una solicitud que utiliza el encabezado X-HubSpot-Signature-v3, deberás 

  • Rechazar la solicitud si la marca de tiempo es anterior a 5 minutos.
  • En la URI de la solicitud, decodifica cualquiera de los caracteres codificados por URL que se enumeran en la siguiente tabla. No necesitas decodificar el signo de interrogación que denota el comienzo de la cadena de consulta.
Valor codificado Valor decodificado
%3A :
%2F /
%3F ?
%40 @
%21 !
%24 $
%27 '
%28 (
%29 )
%2A *
%2C ,
%3B ;
  • Crea una cadena codificada en utf-8 que concatene lo siguiente: requestMethod + requestUri + requestBody + timestamp. La marca de tiempo es proporcionada por el encabezado X-HubSpot-Request-Timestamp.
  • Crea un hash SHA-256 de la cadena resultante usando el secreto de la aplicación como el secreto de la función HMAC SHA-256.
  • Base64 codifica el resultado de la función HMAC.
  • Compara el valor del hash a la firma. Si son iguales, significa que esta solicitud se verificó como proveniente de HubSpot. Se recomienda que uses la comparación de cadenas en tiempo constante para protegerte de los ataques de sincronización.

¿Te resultó útil este artículo?
Con este formulario puedes enviar tu opinión sobre nuestros documentos para desarrolladores. Si tienes comentarios sobre el producto de HubSpot, puedes enviarlos al Foro de ideas.