The success page should never grant anything. Two correct options:
Best: webhook. Handle checkout.session.completed (or subscription events for subscriptions) on your server, verify the signature, and set premium there. The success page just says "thanks, finishing up" and polls your own DB until premium shows.
Also fine as a UX shortcut: verify the session server side.
success_url: "https://mysite.com/success?session_id={CHECKOUT_SESSION_ID}"
Stripe fills in the real id. Then on the server:
const session = await stripe.checkout.sessions.retrieve(sessionId);
if (session.payment_status === "paid" && session.client_reference_id === currentUser.id) {
// grant
}The client_reference_id check (set it to your user id when creating the session) stops someone from reusing another person's session id.
And whatever grants premium must not be writable from the client. If the browser can write premium: true to Firestore, your security rules need fixing too.
premium: !request.resource.data.diff(resource.data).affectedKeys().hasAny(['premium']). sven_fire · edited