Request Signature Verification
Hello,
I'm setting up a webhook to check to make sure a transaction has gone through and I'm writing the code to do the verification with my secret key and I just have some questions on the logic. I'm writing my code in C# and I'm not sure what the raw request body is. I've been trying to research it and havent' had much luck. Do you have any C# code examples of how to do the request signature verification or can give me more details on how to retrieve the raw request body.
Thanks
We Are Mammoth
Discussions are closed to public comments.
If you need help with Cheddar please
start a new discussion.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
Support Staff 1 Posted by Marc Guyer on 20 Jun, 2013 03:50 PM
Hi Michael -- The raw body is just the content of the HTTP POST request. HTTP POST starts with the headers followed by two newline characters followed by the body content. Normally, this is parsed by the HTTP client automatically when the content type is application/x-www-form-urlencoded. Whatever library/framework you're using should still have access to the POST body in it's raw form. I'm not intimately familiar with c# but I'd like to try to help further. Are you using a framework of some sort?
Support Staff 2 Posted by Marc Guyer on 20 Jun, 2013 03:54 PM
Maybe this helps:
http://stackoverflow.com/questions/8386279/get-raw-data-from-http-r...
3 Posted by michael.roth on 20 Jun, 2013 03:56 PM
Thanks, I'll give that a try.
Support Staff 4 Posted by Marc Guyer on 20 Jun, 2013 04:05 PM
Ok, once we have a solution, I hope you can provide a simple example we can use in our docs so others can benefit by our efforts. Please let me know if I can help further.
5 Posted by michael.roth on 21 Jun, 2013 03:38 PM
Hey Marc,
So this is what I have, and it seems like they are not matching up. Am I supposed to do the MD5 hash on the entire request body which is around 4,565 characters long. So here is the code I have and the steps that go along
Grab The Authorization Header
var authorizationHeader = request.Headers["X-CG-SIGNATURE"];
Set The Input Stream The Beginning
request.InputStream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(request.InputStream))
{
Read The Entire Body In
var httpBody = reader.ReadToEnd();
Get The Byte Array of My Secret Key
var secretKeyArray = Encoding.ASCII.GetBytes(_secretKey);
Get MD5 Hash of the Entire Body
var md5Array = CalculateMd5Hash(httpBody);
Build A SHA256 Hash Creator Using My Secret Key as the key
var hash = new HMACSHA256(secretKeyArray);
Get The Hash of The MD5 Hash
var secretKeyHash = hash.ComputeHash(md5Array);
Check Against The Authorization Header
if (BitConverter.ToString(secretKeyHash).Replace("-", "").ToLower() != authorizationHeader.ToLower())
{
throw new Domain.Exceptions.Exception();
}
}
public byte[] CalculateMd5Hash(string input)
{
var md5 = MD5.Create();
var inputBytes = Encoding.ASCII.GetBytes(input);
var hash = md5.ComputeHash(inputBytes);
return hash;
}
Support Staff 6 Posted by Marc Guyer on 21 Jun, 2013 09:43 PM
Hi Michael --
Yes. To be clear, it's the request body not including the headers.
If you're still having trouble getting it match the X-CG-SIGNATURE, I might be able to help further if you post the raw output of each step (i.e., the values of
httpBody
,md5Array
,secretKeyArray
,hash
, and the value of the X-CG-SIGNATURE of the request you're trying to verify)7 Posted by michael.roth on 25 Jun, 2013 03:10 PM
Hey Marc,
Here is some of the values I'm getting. The header to check against, the request body, and the final code I'm getting after doing all the hashes and everything. Let me know if this help or if you have any questions.
Thanks
Michael
From: Marc Guyer <[email blocked]<mailto:[email blocked]>>
Date: Fri, 21 Jun 2013 17:43:49 -0400
To: Michael Roth <[email blocked]<mailto:[email blocked]>>
Subject: Re: Request Signature Verification [Questions #6669]
Support Staff 8 Posted by Marc Guyer on 25 Jun, 2013 03:16 PM
What is the result you get from the MD5 hash? It should be a 32-character hexadecimal number.
Support Staff 9 Posted by Marc Guyer on 25 Jun, 2013 03:21 PM
This returns a byte array:
You then need to convert that to the hex number:
Support Staff 10 Posted by Marc Guyer on 25 Jun, 2013 04:40 PM
I created a quick gist of this based on your work:
https://gist.github.com/marcguyer/5860026
I have no way of testing this so please modify the gist or comment here with changes.
Support Staff 11 Posted by Marc Guyer on 27 Jun, 2013 03:33 PM
Hi Michael -- Sorry for the delay. Github Gist comments do not notify anyone, oddly. So, let's keep the discussion here.
Also, fyi, you can fork the gist into your account and then edit it directly. That's makes it quite easy to see the diff of all the revisions.
I suppose I forgot a line of code there. It would be easier if I had an environment to test this in but I don't. This is a little like flying blind for me.
I updated the gist with the meat of your change (I think). Here's a nice diff:
https://gist.github.com/marcguyer/5860026/revisions
Thanks for the output text file earlier. That helps a bit but there's a big gap of information between the raw post body and the "Final" output. What's the value of
md5String
? Which secret key are you using (which product)? So, to be clear, I can better help out if you'll post:md5String
Kin (Test)
?Also, would it be cleaner to use this to convert to string instead of that StringBuilder loop?
12 Posted by michael.roth on 28 Jun, 2013 01:53 PM
This comment was split into a new discussion: Reactivation After Expired Trial Auto-Cancel
Hey Marc,
I have a question I was wondering if I could get your help on. We're trying to work through a scenario and wanted to get your take on it. So the scenario is that a user signs up for our product on July 1st and gets an invoice built in CG for a billing date of July 14th when his 14 day trial period ends. The user doesn't end up using the product and never inserts his billing information, so on July 14th CG cancels the customer and doesn't run the invoice. Then a month passes by and the user decides that he wants the product now. He re-signs in to our product and inserts his billing information which gets sent to CG. So the previous CG invoice gets run and CG creates the recurring next invoice for a bill date of the next year. Our question is when that previous invoice gets runs does the next invoice get a billing date of a July 14th 2014, which is a year from the bill date of the first invoice, or is it a year from the day that the invoice got ran, which was August 1st. For our situation we would want the next invoice bill date to be a year from when the invoice ran, so August 1st 2014, not July 1st 2014. If you could give us some guidance on what the dates will be set to and what we might do to update the dates that would be great.
Thanks again for the help,
Michael
Jess Pendley closed this discussion on 21 Nov, 2013 07:44 PM.