4 ms·
What I find bleak about the situation, is that it is a glaring design-fail, even though everyone involved should have the necessary expertise to do better. A ca
by Perseids 4y ago
What I find bleak about the situation, is that it is a glaring design-fail, even though everyone involved should have the necessary expertise to do better. A callback from your payment provider should never go through a best-effort WAF. Instead, as you already have a strong business relationship, you could easily exchange/store/configure strong credentials with stripe [1]. When even a security professional doesn't do that, what does it say about the state of documentation of this feature?
Looking at the documentation directly, what they advise you to do is kind of the worst idea they could come up with: https://stripe.com/docs/webhooks/signatures https://stripe.com/docs/webhooks/signatures – you need custom logic[2] to verify that their MAC ("signature" they call it incorrectly) is valid and you need to configure a different secret for each of your endpoints. And then you still need to handle replay attacks somehow, which is its own nightmare to do correctly. It's no wonder the WAF can't do that for you.
From a few years old personal experience, I'm really irritated by stripes web-hook approach overall. Payment process information is such a vital business concern that "let's try to call them and if that fails... well we tried" is broken on principal alone. The obvious approach is to have an event list which you as customer long-poll or just poll every few seconds if your framework doesn't support async well. This is also trivial to do securely: You're HTTPS library already authenticates stripe during the TLS handshake and that is all that is necessary.
[1] Best case scenario: Let stripe authenticate with mutual TLS, but I know this is quite a long way away from typical web server configurations.
[2] Stripe's approach very much reminds of DPoP https://news.ycombinator.com/item?id=31266575 https://news.ycombinator.com/item?id=31266575 which shall in now way be construed as a compliment.
- davedx 4y ago> The obvious approach is to have an event list which you as customer long-poll or just poll every few seconds This is also much much easier for the payments integrations developers to test, compared to all the messing about and running dodgy proxies that testing webhooks involves. Webhooks for critical application paths just seem like a bad idea all around really
- bmizerany 4y ago> Webhooks for critical application paths just seem like a bad idea all around really Well, put. I've been deep in the Stripe API for a while now, and the invoices API provides up-to-date account status information and what a customer is paying for. This can be referenced as needed and, if desired, cached with some TTL and referenced as the "truth." Then webhooks can be viewed as a convenient way to bust the cache quicker than waiting for the TTL to expire. It could be better, but it provides the necessary information without relying on webhooks. An example of how we use this API as a form of entitlement checks at Tier can be found here: https://github.com/tierrun/tier/blob/f7c32426d30ca314706ca7e64399340f306f1d0b/control/usage.go#L89-L116 https://github.com/tierrun/tier/blob/f7c32426d30ca314706ca7e...
- lvice 4y agoI just would like to give my opinion on some of your points, which I don't agree with: > Looking at the documentation directly, what they advise you to do is kind of the worst idea they could come up with: https://stripe.com/docs/webhooks/signatures https://stripe.com/docs/webhooks/signatures – you need custom logic[2] to verify that their MAC ("signature" they call it incorrectly) is valid and you need to configure a different secret for each of your endpoints It certainly help that I use their official SDK, but it's one line of code to add the signature validation. Also, I'm not sure why you would want to create a lot of endpoints to listen to these webhook. I simply have one, and the Stripe SDK helps me in determine the event type, its deserialization, etc. > Payment process information is such a vital business concern that "let's try to call them and if that fails... well we tried" is broken on principal alone That's not how it works. The webhooks keep retrying with exponential backoff until they succeed. You can also manually retrigger them for individual events. > The obvious approach is to have an event list which you as customer long-poll or just poll every few seconds if your framework doesn't support async well Nothing is preventing you to do that. In fact, in my codebase I do polling to the Stripe API as a fallback to check if payment is successful in case there are issues with webhooks. But it's nice to have the webhook telling you immediately if a payment fails/succeed, in order to give feedback to the user fast about the status of his payment (and not wait the next long polling iteration) Not everything on Stripe is perfect, but I do find it really pleasant to work with in general
- Perseids 4y agoThanks for your remarks and corrections. While what you say is correct, it doesn't apply to the problem Troy Hunt faced. What he needs is DDOS protection on his API. The request authentication Stripe provides is too complicated to be checked by the web application firewall. The (edit:) pragmatic approach is to a) not use webhooks or b) let Stripe connect to you via HTTPS (to prevent replay attacks and leakage of the secret URI), give Stripe a secret URI, whitelist the secret URI in the WAF and verify the payload MAC via the official SDK. > in order to give feedback to the user fast about the status of his payment (and not wait the next long polling iteration) Nitpick: The long poll / Server Sent Event should respond immediately once there is new data available, so it should not be slower than the webhook.
- philipwhiuk 4y agoYeah, Stripe is well documented but very ugly to actually handle in practice.
- AtNightWeCode 4y agoYou should not poll a payment provider in a general flow. Do you realize how many requests that will cause if everybody did that? A payment flow is event-driven by nature. The payment provider pushes the states back to the initiating system. If that fails it is up to the consumer to detect problems and make sure that the system is in sync with the provider. Some payment providers do push data up to at least 24h. It is an obvious design flaw...