Unable to Validate Hubspot Signature V3

I’m experiencing issues validating the request. Here’s my code, what am I getting wrong here? Please note the _fullWebHookUrl is the entire path (https://b692-98-231-78-177.ngrok.io/api/v1/HubSpotWebhooks/PostNotification)
Thanks for the help, I’m pretty well frustrated at this point. I can’t see what is going wrong here.

private bool ValidateRequest(HttpRequest httpRequest, dynamic requestBody)
{
httpRequest.Headers.TryGetValue(“X-Hubspot-Request-Timestamp”, out var timeStamp);
httpRequest.Headers.TryGetValue(“X-Hubspot-Signature-V3”, out var v3);
httpRequest.Headers.TryGetValue(“X-Original-Host”, out var originalHost);

var webhookUrl = $“{httpRequest.Scheme}://{originalHost}{httpRequest.Path}”;
var appSecret = _hubSpotOptions.Value.Secret;

var _fullWebhookUrl = new Uri(webhookUrl).AbsoluteUri;

HMACSHA256 hashObject = new(Encoding.UTF8.GetBytes(appSecret));

var data = string.Concat(httpRequest.Method, _fullWebhookUrl, requestBody, timeStamp);
byte[] utf = Encoding.UTF8.GetBytes(data);

var signatureV3 = hashObject.ComputeHash(utf);
var encodedSignature = Convert.ToBase64String(signatureV3);

bool validRequest = v3.Equals(encodedSignature);
return validRequest;
}

@Teun , anything stick out here :thinking:

Hi @dennisedson and @GPhillips9 ,

Any chance that you have some logs or errors that could help us out here?

Got it figured out. The requestBody was being passed a “dynamic” vs a string and therefore the comparison was invalid. From the caller method, the working code is this:

string json = JsonConvert.SerializeObject(notification);
var isValidRequest = ValidateRequest(json)
/// <summary>
/// Validates incoming request - signature v3 version
/// </summary>
/// <param name=“requestBody”></param>
/// <returns></returns>
private bool ValidateRequest(string requestBody)
{
var httpRequest = HttpContext.Request;
httpRequest.Headers.TryGetValue(“X-Hubspot-Request-Timestamp”, out var timeStamp);
httpRequest.Headers.TryGetValue(“X-Hubspot-Signature-V3”, out var v3);
httpRequest.Headers.TryGetValue(“X-Original-Host”, out var originalHost);

DateTime dt = DateTimeOffset.FromUnixTimeMilliseconds(Convert.ToInt64(timeStamp)).DateTime;
DateTime now = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now);

var difference = (int)now.Subtract(dt).TotalMinutes;

if (difference < 5)
{
var webhookUrl = $“{httpRequest.Scheme}://{originalHost}{httpRequest.Path}”;
var appSecret = _hubSpotOptions.Value.AppSecret;

HMACSHA256 hashObject = new(Encoding.UTF8.GetBytes(appSecret));

var data = string.Concat(httpRequest.Method, webhookUrl, requestBody, timeStamp);
byte[] utf = Encoding.UTF8.GetBytes(data);

var signatureV3 = hashObject.ComputeHash(utf);
var encodedSignature = Convert.ToBase64String(signatureV3);

return v3.Equals(encodedSignature);
}

return false;
}