Back to Practice

Practice · Payments · Card 2

Why does this webhook controller skip CSRF?

A controller that takes Stripe webhook posts. skip_before_action :verify_authenticity_token on the first line. Why is that safe?

The code

class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  def stripe
    event = Stripe::Webhook.construct_event(
      request.body.read,
      request.env["HTTP_STRIPE_SIGNATURE"],
      ENV.fetch("STRIPE_WEBHOOK_SECRET")
    )
    ProcessStripeEventJob.perform_later(event.id)
    head :ok
  rescue Stripe::SignatureVerificationError
    head :bad_request
  end
end

The question

Why is skipping CSRF safe here, and what's actually preventing an attacker from forging webhook calls?

Take a moment. CSRF protects against one threat model; webhook signatures protect against another. What are they each defending against, and why does skipping one make sense when the other is in place?