Firebase + Stripe Integration Security

Share

To secure Firebase + Stripe integration, you need to: (1) handle Stripe webhooks in Cloud Functions using rawBody for signature verification, (2) use Firebase Admin SDK to update Firestore subscription fields, (3) protect subscription fields in Security Rules so users cannot modify them, (4) link checkout sessions to Firebase UIDs, and (5) verify authentication in callable functions. This blueprint keeps payment state secure and server-authoritative.

Setup Time2-3 hours

TL;DR

Handle Stripe webhooks in Cloud Functions, not client-side. Verify webhook signatures, use Firebase Admin SDK to update Firestore, and protect subscription status with Security Rules. Never trust client payment confirmations.

Webhook Cloud Function Firebase Stripe

functions/src/stripe.ts
import * as functions from 'firebase-functions'
import Stripe from 'stripe'
import * as admin from 'firebase-admin'

const stripe = new Stripe(functions.config().stripe.secret_key)
const webhookSecret = functions.config().stripe.webhook_secret

export const stripeWebhook = functions.https.onRequest(async (req, res) => {
  const signature = req.headers['stripe-signature'] as string

  let event: Stripe.Event

  try {
    event = stripe.webhooks.constructEvent(
      req.rawBody,
      signature,
      webhookSecret
    )
  } catch (err) {
    console.error('Webhook signature verification failed')
    res.status(400).send('Invalid signature')
    return
  }

  const db = admin.firestore()

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session
      await db.collection('users').doc(session.client_reference_id!).update({
        stripeCustomerId: session.customer,
        subscriptionStatus: 'active',
        updatedAt: admin.firestore.FieldValue.serverTimestamp(),
      })
      break
    }
    case 'customer.subscription.deleted': {
      const subscription = event.data.object as Stripe.Subscription
      const userQuery = await db.collection('users')
        .where('stripeCustomerId', '==', subscription.customer)
        .get()

      if (!userQuery.empty) {
        await userQuery.docs[0].ref.update({
          subscriptionStatus: 'canceled',
        })
      }
      break
    }
  }

  res.json({ received: true })
})

Create Checkout (Callable Function)

functions/src/checkout.ts
import * as functions from 'firebase-functions'
import Stripe from 'stripe'

const stripe = new Stripe(functions.config().stripe.secret_key)

export const createCheckout = functions.https.onCall(async (data, context) => {
  // Verify authentication
  if (!context.auth) {
    throw new functions.https.HttpsError('unauthenticated', 'Must be logged in')
  }

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    line_items: [{ price: data.priceId, quantity: 1 }],
    success_url: `${data.origin}/success`,
    cancel_url: `${data.origin}/cancel`,
    client_reference_id: context.auth.uid,  // Link to Firebase user
  })

  return { sessionId: session.id, url: session.url }
})

Firestore Security Rules Firebase

firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      // Users can read their own data
      allow read: if request.auth.uid == userId;

      // Users cannot modify subscription fields
      allow update: if request.auth.uid == userId
        && !request.resource.data.diff(resource.data)
            .affectedKeys()
            .hasAny(['subscriptionStatus', 'stripeCustomerId']);
    }
  }
}

Protect subscription fields in rules. Users should never be able to modify their own subscription status. Only Cloud Functions with Admin SDK can update these fields.

Security Checklist

Pre-Launch Checklist

Webhook signatures verified

rawBody used for signature verification

Subscription fields protected in rules

Callable functions check auth

Checkout linked to Firebase UID

Supabase + Stripe Alternative Stripe Webhooks Deep Dive Cloudflare Workers Edge Security

Check Your Payment Integration

Scan for webhook and payment security issues.

Start Free Scan
Security Blueprints

Firebase + Stripe Integration Security