This document has a sequence diagram (annotated and shown below) explaining how Stripe handle's a Checkout Session.

My question : When a customer is returned to the successUrl = www.example.com/some/specific/path, how can www.example.com (either client or server) verify it is truly coming from stripe.com instead of a malicious user?

Please see the sequence diagram below more details.

enter image description here

  • Why does it have to? Why can't it check if the payment went through or not? Commented Jan 21 at 12:24
  • @user1068636: You should not have any logic that depends on the fact from what website the client was redirected. Instead, you should just verify, if the payment was really done, by contacting Stripe server from your server. See the answer of "Bobson".
    – mentallurg
    Commented Jan 21 at 17:15
  • You don't have to verify anything on the success page. Follow the OP's link to the Stripe documentation -- or just look at the big diagram right in front of you. See the arrow saying "Handle fulfillment"? This is where the order fulfillment happens (via webhooks), not on the success page. The success page just displays a message. It can be a purely static site.
    – Ja1024
    Commented Jan 21 at 18:52

2 Answers 2


There's nothing that example.com can do to verify the redirect. After all, the request for the page is coming from the client (regardless of whether it's on behalf of Stripe or a malicious user) and the client can't be trusted. What the server can do is separately verify the transaction with Stripe, using its own (trusted) connection and credentials.

There's two ways to do this, and while I haven't integrated to Stripe, based on this page it looks like they support both. The first option is to query Stripe's API for the status of the payment. The flow here is that when the "success" page is requested, first the server issues a call to Stripe to find the status, and then uses that status to decide between returning the actual success or displaying an error. The second option is to implement a webhook, where Stripe's server directly contacts example.com's server to provide a "this payment succeeeded" message. In this flow, the "success" page would actually just be a "please wait" page that keeps checking whatever you use as a data store to see whether Stripe's reported a success, and only then displays the success to the user. Meanwhile, the webhook endpoint would record the result from Stripe when it's delivered. If the webhook message is fast enough, the "please wait" could just immediately go to a success, but flow-wise it's still a step along the way.

Either way, the key is that the example.com server and the Stripe API are communicating directly with each other without needing to trust anything from the client. All the redirect does is trigger example.com to look up the status for itself.

  • This doesn't make sense. What kind of attack do you think you're preventing here? If another site redirects random people to the success page of example.com, there's no harm at all. In the worst case, the people will be irritated from seeing a "Payment Successful" page when they didn't do any payment, but the payment page won't even display any details about the payment (this would require the other site to know the Stripe session ID). The same can happen in any shop which has static success and error pages. Yeah, you could link directly to a page which says "Success" or "Error". So what?
    – Ja1024
    Commented Jan 20 at 17:15
  • @Bobson: "... the request ... is coming from the client ... and the client can't be trusted" - Exactly. I'd suggest you to add, that it makes no sense for the server to talk about "redirect". Server should consider each request just as a request, without any assumptions, without trusting any data sent by client.
    – mentallurg
    Commented Jan 20 at 17:46
  • You're saying "exactly" and then claim the exact opposite of what Bobson just wrote. Are you sure you understand the topic here and the different answers?
    – Ja1024
    Commented Jan 20 at 18:13
  • @Ja1024 If the success page just says "success", there's no real attack. If the success page says "success" and marks it as a success in the merchant's system (without verification), then just jumping to that page gets you free stuff. And in the OP's scenario, where the merchant's site wants to verify that the redirect came from Stripe, then my assumption is that the goal is to mark it as a success if the redirect legitimately came from Stripe (otherwise, why would they care?). And that's not safe.
    – Bobson
    Commented Jan 21 at 9:07
  • This is not how Stripe works. The success page has nothing to do with order fulfillment; this is done via webhooks. This is very clear from both the protocol description and the example code on the Stripe page. Sure, the owner of example.com could decide to not implement a Stripe checkout and instead set up a page which sends free products to anybody who visits the page. But this is completely unrelated to Stripe.
    – Ja1024
    Commented Jan 21 at 9:38

First a clarification: The success page is not responsible for order fulfillment. Its sole purpose is to display a confirmation message to the user along the lines of "We've received your payment". The actual order fulfillment is implemented separately via webhooks. So if you think you have to authenticate the visitor on the success page to protect the checkout process, this is incorrect.

The server doesn't have to (and cannot) ensure that a visitor of the success page actually has been redirected there from Stripe. The success page just displays a message, it doesn't trigger order fulfillment. If it does, then you need to remove that immediately and implement the Stripe protocol as described. If you're just worried that people might get a bogus payment confirmation when they (accidentally) visit the success page directly rather than through Stripe, then you can include the Checkout Session ID as a URL parameter. This allows you to distinguish between random page visitors and actual customers performing a Stripe checkout.

The client doesn't have to do any checks either. They can trust the redirect to the success page, because 1) the Stripe API uses HTTPS, so an attacker cannot manipulate the success URL transmitted from example.com to Stripe during session creation, and 2) the Stripe payment page which issues the redirect back to example.com also uses HTTPS to prevent attackers from reading or changing the traffic.

Without HTTPS, there would be bigger problems than a malicious redirect, because a man-in-the-middle attacker could read the payment information.

  • 1
    That doesn't help with some other malicious site redirecting directly to example.com's success page, bypassing Stripe entirely.
    – Bobson
    Commented Jan 20 at 16:43
  • There's nothing malicious about redirecting to a page which simply says something like "Payment Succeeded". If Stripe isn't involved, there's no transaction at all, so nobody claims to buy anything, nobody has to pay anything, nobody expects to get any products, and no sensitive data is exchanged. Both example.com are perfectly safe. At worst, you could say a status page which just displays a message without checking the actual status is a bad UI.
    – Ja1024
    Commented Jan 20 at 17:25
  • "The client can trust the redirect, because 1) the Stripe API uses HTTPS" - This statement is wrong. It doesn't matter at all how secure is connection to Stripe. Server receives a request, and relevant are only data that client sends to the client.
    – mentallurg
    Commented Jan 20 at 17:51
  • 1
    OK, I understand your point. I'm not sure why somebody would implement a non-Stripe order fulfillment on the success page when they've already implemented a Stripe order fulfillment via webhooks, but maybe the OP is actually trying to do this. Then I think the answer is not to jump through hoops to check the payment status on the success page page. But simply: Implement the Stripe protocol as described.
    – Ja1024
    Commented Jan 21 at 9:49
  • 1
    Maybe you should read the whole text, not just part of a sentence. Then you might actually understand the issue. The OP incorrectly assumes that they have to verify payment on the success page, and they incorrectly assume that the right way to do that is to "verify the redirect". Both assumptions come from a misunderstanding of the Stripe protocol (which you seem to struggle with as well). The success page doesn't have to verify anything. Payment verification and order fulfillment happens in a completely different step.
    – Ja1024
    Commented Jan 21 at 19:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .