Stripe Ownership and Webhooks

SecurityBilling ownershipVerified webhook flow

Stripe billing is protected with a combination of session checks, customer ownership checks, and verified webhook processing.

This area matters because billing security is not only about creating checkout sessions. It is also about proving which user owns which Stripe resources and trusting webhook updates only after signature verification.

Related docs

For the broader billing architecture, see Billing and Stripe. For implementation details, continue with Configure Stripe.

What this security area covers

Ownership checks

Stripe customers, subscriptions, and payments are tied back to authenticated users before sensitive operations are allowed.

Verified webhook entry

The webhook route rejects unverified requests before any billing event is processed.

State synchronization

Long-lived subscription and payment state is updated from verified Stripe events instead of trusting only redirect-time client behavior.

Ownership model

Ownership model

The app ties Stripe objects back to the authenticated user through:

  • stripeCustomerId stored on the user
  • userId stored in Stripe metadata
  • service-level checks before read or write operations

This creates a stronger link between application identity and Stripe resources than using Stripe objects alone.

Examples of current checks

  • customer reads and updates verify ownership
  • payment intents are checked against metadata.userId
  • active subscription lookup is scoped through the user-linked customer

These checks help prevent users from reading or mutating billing data that does not belong to them.

Webhook protection

The webhook route verifies the stripe-signature header before processing any event.

Only after signature verification does the route call handleStripeWebhookEvent.

Why webhook sync matters

Checkout is not enough on its own. Long-lived billing state must be synchronized from Stripe events so the local database reflects:

  • subscription status
  • current period end
  • one-time payments
  • recurring invoice payments

That keeps billing state reliable even when payment events happen after redirects, retries, or subscription updates outside the browser.

Main files

  • src/app/api/stripe/webhook/route.ts
  • src/server/services/billing/customer.ts
  • src/server/services/billing/webhook-sync.ts

Security rule

Treat webhook verification and ownership checks as mandatory billing boundaries, not optional implementation details.