Stripe .net "The signature for the webhook is not present in the Stripe-Signature header."

Viewed 6338

I am using Stripe.net SDK from NuGet. I always get the

The signature for the webhook is not present in the Stripe-Signature header.

exception from the StripeEventUtility.ConstructEvent method.

[HttpPost]
public void Test([FromBody] JObject incoming)
{
    var stripeEvent = StripeEventUtility.ConstructEvent(incoming.ToString(), Request.Headers["Stripe-Signature"], Constants.STRIPE_LISTENER_KEY);
}

The WebHook key is correct, the Request Header contains "Stripe-Signature" keys.

I correctly receive incoming data from the Webhook tester utility (using nGrok with Visual Studio).

the secureCompare method seems to be the culprit => StripeEventUtility.cs

I tried to manipulate the incoming data from Stripe (Jobject, string, serializing...). The payload signature may cause some problem.

Has anybody had the same problem?

4 Answers

As per @Josh's comment, I received this same error

The signature for the webhook is not present in the Stripe-Signature header.

This was because I had incorrectly used the API secret (starting with sk_) to verify the HMAC on EventUtility.ConstructEvent.

Instead, Stripe WebHook payloads are signs with the Web Hook Signing Secret (starting with whsec_) as per the docs

The Web Hook Signing Secret can be obtained from the Developers -> WebHooks page:

Web Hooks Signing Secret

The error can also occur because you are using the secret from the Stripe dashboard. You need to use the temporary one generated by the stripe cli if you are using the CLI for testing.

To obtain it run this:

stripe listen --print-secret

Im not sure about reason of this, but Json readed from Request.Body has a little bit different structure than parsed with [FromBody] and Serialized to string.

Also, you need to remove [FromBody] JObject incoming because then Request.Body will be empty.

The solution you need is:

[HttpPost]
public void Test()
{
    string bodyStr = "";
    using (var rd = new System.IO.StreamReader(Request.Body))
      {
          bodyStr = await rd.ReadToEndAsync();
      }
    var stripeEvent = StripeEventUtility.ConstructEvent(bodyStr, Request.Headers["Stripe-Signature"], Constants.STRIPE_LISTENER_KEY);
}

I was also receiving the same exception message when I looked at it in the debugger but when I Console.WriteLine(e.Message); I received a different exception message.

Received event with API version 2020-08-27, but Stripe.net 40.5.0 expects API version 2022-08-01. We recommend that you create a WebhookEndpoint with this API version. Otherwise, you can disable this exception by passing throwOnApiVersionMismatch: false to Stripe.EventUtility.ParseEvent or Stripe.EventUtility.ConstructEvent, but be wary that objects may be incorrectly deserialized.

I guess your best bet is to set throwOnApiVersionMismatch to false;

EventUtility.ParseEvent(json, header, secret, throwOnApiVersionMismatch: false)

Related