1

so I am setting up stripe webhooks for several use-cases, and following the docs, I was not able to get a working webhook response. I kept getting this error.

"Webhook Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?"

I followed the docs and understood that this just means I need to convert the body to raw data instead of another format(stripe needs raw data to make the secure connection). I tried doing this in several different ways(I have a few down below).

app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {

New code attempt :

app.use((req, res, next) => {
  if (req.originalUrl === "/webhook") {
    next();
  } else {
    bodyParser.json()(req, res, next);
  }
});

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {

As you can see, I tried all of the ways that the stripe docs recommended and even tried some ways from this similar SOF question, but was not able to do it. I also tried with bodyPaser or express and tried several smaller things too. In our app we are using a firebase backend, with several normal cloud functions, and we decided to use express with all the stripe code since that is what the stripe docs use. After trying for so long with express and fierbase, I decided to do it with just a firebase onRequest method and used the req.rawBody method.

  exports.stripeWebhook = functions.https.onRequest((request, response) => {
  const stripeWebhookSecretKey = functions.config().stripe.webhook_secret_key;
  
  let event;
  
  ...
  const payloadData = request.rawBody;
  const payloadString = payloadData.toString();
  const webhookStripeSignatureHeader = request.headers['stripe-signature'];

  event = stripe.webhooks.constructEvent(payloadString, webhookStripeSignatureHeader, stripeWebhookSecretKey);
  ...
});

This worked right away and although I don't think my boss would mind, having all the stripe code in express would be ideal, and just want to know why this might be happening. Thanks

seth8656
  • 104
  • 5

1 Answers1

0

Stripe requires the raw body of the request to perform signature verification. If you’re using a framework, make sure it doesn’t manipulate the raw body. Any manipulation to the raw body of the request causes the verification to fail.[1]

The main two reasons behind getting “No signatures found matching the expected signature for payload” error are:

  • Using a wrong webhook secret. make sure you are using the correct one[2].
  • The request rawbody is changed. make sure that nothing is changing your request body (e.g. compressor, json middlewares )

You can refer to this complete sample Firebase function that implement a webhook endpoint for Stripe Events[3].

[1] https://stripe.com/docs/webhooks/signatures#:~:text=Stripe%20requires%20the%20raw%20body%20of%20the%20request%20to%20perform%20signature%20verification.%20If%20you%E2%80%99re%20using%20a%20framework%2C%20make%20sure%20it%20doesn%E2%80%99t%20manipulate%20the%20raw%20body.%20Any%20manipulation%20to%20the%20raw%20body%20of%20the%20request%20causes%20the%20verification%20to%20fail.

[2] https://stripe.com/docs/webhooks/signatures#:~:text=Before%20you%20can%20verify%20signatures%2C%20you%20need%20to%20retrieve%20your%20endpoint%E2%80%99s%20secret%20from%20your%20Dashboard%E2%80%99s%20Webhooks%20settings.

[3] https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-payments/functions/src/index.ts#L676

os4m37
  • 655
  • 1
  • 5
  • Thank you very much. All the links provided helped. I have a working solution with firebase, however, I wanted to know if using "functions.https.onRequest(app)". 'app' being my express app, would firebase manipulate the body on this? I tried doing it this way for hours and could not figure it out, so this leads me to believe that firebase running express code somehow changes the body. – seth8656 Mar 07 '23 at 11:02
  • Firebase is wrapping your express app, which means it has impact on your integration flow AFAIK. However, in all cases you should be using req.rawBody and not req.body. – os4m37 Mar 09 '23 at 08:27
  • Currently in my normal firebase.http.onRequest function, I am using req.rawBody and that is why it is working. However when I wrap my express app and use req.rawbody I get the type error, 'rawBody does not exist on type Request'. I tried setting the type of the request in the params as functions.http.request(same type as in the normal firebase function) but that returned a different express type error. I am not sure if you are familiar with typescript, but I am not sure how to type this without typecasting it and I really don't want to manipulate my types. PS thank you for the support! – seth8656 Mar 09 '23 at 15:53