Validar solicitudes de HubSpot

 

Para garantizar que las solicitudes que tu integración recibe de HubSpot realmente provengan de HubSpot, completamos dos encabezados: X-HubSpot-Signature y X-HubSpot-Signature-Version.

El encabezado X-HubSpot-Signature contendrá la firma que deberá verificarse. El método utilizado para verificar la firma dependerá de la versión de la firma.

El encabezado X-HubSpot-Signature-Version contendrá un número de versión, es decir,  v2, que indicará qué método debería usarse para verificar la firma incluida en X-HubSpot-Signature.

Consulta las páginas de documentación a continuación para ver los detalles de la verificación de las diferentes versiones de la firma.


Validando la solicitud de solicitud v1:

Cuando se envíe la solicitud de HubSpot con el encabezado X-HubSpot-Signature-Version establecido en v1, el encabezado X-HubSpot-Signature será un HAC-256 hash creado usando el secreto del cliente de tu aplicación con detalles de la solicitud.

Para verificar esta firma, realiza los siguientes pasos:

  • Crea una cadena que concatene lo siguiente: Secreto del cliente cuerpo de solicitud (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.

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


Validación de la firma de solicitud v2:

Cuando se envíe la solicitud de HubSpot 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 con detalles de la solicitud.

Para verificar esta firma, realiza los siguientes pasos:

  • Crea una cadena que concatene lo siguiente: Secreto del cliente + método http + URI + cuerpo de solicitud (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:

  • Secreto del cliente : yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
  • Método HTTP: POST
  • URIhttps://www.example.com/webhook_uri
  • Cuerpo de solicitud: {"example_field":"example_value"} 

 

Validación de las firmas de solicitud v3

Cuando se envíe la solicitud de HubSpot con el encabezado X-HubSpot-Signature-Version establecido en v3, el encabezado X-HubSpot-Signature será un hash SHA-256 hash creado usando el secreto del cliente de tu aplicación con detalles de la solicitud. También incluirá un encabezado X-HubSpot-Request-Timestamp.
  • Rechaza la solicitud si la marca de tiempo es anterior a 5 minutos.
  • 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, esta solicitud se verificó como proveniente de Hubspot. Recomendamos usar la comparación de cadenas de tiempo constante para evitar los ataques de tiempo.

¿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.