I am trying to verify incoming webhook signatures in C# using the following code.
public async Task Validate(string sharedSecretKey, HttpRequest request)
{
request.EnableBuffering();
using var streamReader = new StreamReader(request.Body, leaveOpen: true);
// Read out the body - this is required to generate the HMAC signature.
string requestBody = await streamReader.ReadToEndAsync();
request.Body.Position = 0; // Reset position.
using (HMACSHA256 hmac = new HMACSHA256(secretBytes))
{
byte signatureBytes = hmac.ComputeHash(requestBodyBytes);
calculatedSignature = Convert.ToBase64String(signatureBytes);
}
return hmacHeader == calculatedSignature;
}
However, the value outputted in “calculatedSignature” does not match the value provided in the header of the webhook request. I am confident I am using the correct secret value (coming from the “Client secret” section of the Client credentials page against the integrated app). I have tried multiple different way of generating the signature but getting the same output each time which never matches the value coming from Shopify. Any help would be appreciated.
Hey, sorry to hear about this problem. Before digging further can you please checkout this issue and see if the suggestions made here solve the problem you’re facing?
Hi, I am confident the value being used for the secret does not contain any spaces or quotes and it the same value used during the integration creation. My only idea at the moment is the encoding of the request but the docs do not provide a C# example and I have tried many different approaches to this and get the same outcome.
if (!string.IsNullOrWhiteSpace(hmacHeader))
{
var sharedSignatureBytes = Encoding.UTF8.GetBytes(clientSecret);
using var hmac = new HMACSHA256(sharedSignatureBytes);
// Copy the request body to a memory stream then convert it to a byte.
using MemoryStream dataStream = new();
await req.Body.CopyToAsync(dataStream);
var dataBytes = dataStream.ToArray();
// Compute a hash of the body based on the signature.
var generatedHmacHashBytes = hmac.ComputeHash(dataBytes);
var generatedSignature = Convert.ToBase64String(generatedHmacHashBytes);
// Compare that signature to the one that Shopify generated and sent over.
return hmacHeader == generatedSignature;
}
else
{
return false;
}
}