Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add env parameter to Stripe metadata, check value before processing events #6234

Merged
merged 7 commits into from
May 4, 2023

Conversation

justynoh
Copy link
Contributor

@justynoh justynoh commented May 2, 2023

Problem

Our Stripe webhooks are being sent everywhere! This risks our webhook handlers being disabled by Stripe for consistently rejecting webhooks that aren't meant for each environment.

Solution

An env parameter is added to the Stripe metadata. This enables us to check which environment the webhook is meant for when it is received. If the webhook is not meant for the environment, we return a 202 Accepted.

Additional random stuff this PR includes:

  • Also, Joi validation was breaking for previous payment endpoint. It's not necessary, so i did a small refactor to remove it in payments.controller.
  • Need to have better response codes for Stripe webhooks, so repurposed mapRouteErr to be used in webhook handler as well.

Sorry for the slight mess! 🙏

Breaking Changes

  • Yes - this PR contains breaking changes
    • The shape of Stripe metadata has changed, and so some webhooks may fail if not handled properly. Currently, the requirement on the metadata object having the env value is not enforced, to enable backward-compatibility on webhooks that did not have the env parameter previously. Once we stop receiving such webhooks, we should enable these checks in stripe.utils.ts.

Deploy Notes

  • SSM_ENV_SITE_NAME : set this to prod for production prior to deployment

@justynoh justynoh requested review from KenLSM and wanlingt May 3, 2023 06:44
string,
| StripeMetadataInvalidError
| StripeMetadataValidPaymentIdNotFoundError
| StripeMetadataIncorrectEnvError
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm would it make more sense to check for the env in a separate function instead of getMetadataPaymentId? then we can also do the check earlier and avoid processing the webhook (in stripe.controller.ts) if it's from the wrong env

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm, we could but it would still be quite messy. The target of the call to getMetadataPaymentId is different based on different cases (see the switch in handleStripeEventUpdates), since the metadata to be checked exists in different places in each type of event. If in the future we want to extract other data from the metadata, we can expand the scope of this function to extract all relevant values. It's just that currently, we only need the payment id.

@justynoh justynoh requested review from LinHuiqing and wanlingt May 3, 2023 07:59
@@ -43,6 +81,7 @@ export const getChargeIdFromNestedCharge = (
const isStripeMetadata = (
obj: Stripe.Metadata,
): obj is StripePaymentMetadataDto =>
// hasProp(obj, 'env') && // TODO: Make this required later
Copy link
Contributor

@wanlingt wanlingt May 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we create an issue tagged to the TODO so we don't forget about this later on?

meta: { ...logMeta, metadata },
})
return err(new StripeMetadataValidPaymentIdNotFoundError())
}
// Explicit check for metadata.env to ensure that legacy metadata which does
// not have the env value still gets processed.
// TODO: remove the existence check later.
Copy link
Contributor

@wanlingt wanlingt May 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: same for the TODO here! :)

Copy link
Contributor

@wanlingt wanlingt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! there's a typo in your PR description btw, i think you meant payments.controller instead of payments.service.

Adding more context in this comment for posterity (feel free to add on + add it to the PR description also):

  • Webhooks are sent to all connected platform accounts' endpoints when a Stripe account is connected to multiple platform accounts
  • Stripe disables endpoints if an endpoint hasn’t responded with a 2xx HTTP status code for multiple days in a row (Stripe docs)
  • test Events are sent to both live and test connect webhook endpoints (Stripe docs). Instead of using the livemode property, we're choosing to use env instead to better distinguish between our different environments.

@justynoh
Copy link
Contributor Author

justynoh commented May 4, 2023

You're right, updated the PR description! Also for the TODOs, will open a PR for it almost immediately. Just need to make sure we only merge it in a week after this PR goes out

@justynoh justynoh merged commit 178942c into develop May 4, 2023
@justynoh justynoh deleted the fix/cross-env-webhooks branch May 4, 2023 06:33
@wanlingt wanlingt mentioned this pull request May 8, 2023
19 tasks
LinHuiqing pushed a commit that referenced this pull request May 11, 2023
…ing events (#6234)

* fix: add env parameter to Stripe metadata, check value before processing events

* fix: better error codes for webhook handler returns

* fix: remove unneeded Joi validation on previous payment endpoint

* chore: remove unused variable

* chore: clarify comment

* test: add SSM_ENV_SITE_NAME to test env

* test: update tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants