Reputation: 1183
Stripe::Webhook.construct_event
is raising Stripe::SignatureVerificationError
when running request specs with rspec.
Using byebug
Stripe::Webhook::Signature.verify_header
is returning true. After continuing, the exception Stripe::SignatureVerificationError
is raised.
From reviewing the source, it seems that the first call in Stripe::Webhook.construct_event
is Stripe::Webhook::Signature.verify_header
.
Why would the call in the debug console return true but apparently return false when it is called in .construct_event
?
class WebHooks::StripeController < WebHooksController
# Entry point for Stripe webhooks. This method
# will verify the signature and dispatch to the
# appropriate method. It will log warning if
# the webhook type is unknown. The method dispatched is the
# webhook type with underscores instead of dots.
def create
payload = request.body.read
sig_header = request.headers['Stripe-Signature']
event = nil
byebug
# Byebug Console
Stripe::Webhook::Signature.verify_header(payload, sig_header, Rails.application.credentials.stripe[:signing_secret])
# => True, this returns true
begin
event = Stripe::Webhook.construct_event(
payload, sig_header, Rails.application.credentials.stripe[:signing_secret]
)
rescue JSON::ParserError => e
# Invalid payload
head :unprocessable_entity
return
rescue Stripe::SignatureVerificationError => e
# Invalid signature
Rails.logger.error("⚠️ Stripe signature verification failed.")
head :unauthorized
return
end
type = event.type.gsub('.', '_')
begin
public_send(type)
rescue NoMethodError
Rails.logger.warn("Unknown webhook type: #{params[:type]}")
head :unprocessable_entity
end
end
end
require 'rails_helper'
RSpec.describe "WebHooks::Stripe::Signature", type: :request do
context "with a valid signature" do
it "returns 200" do
event = { type: "not_implemented" }
headers = {
"Stripe-Signature" => stripe_event_signature(event.to_json)
}
post "/web_hooks/stripe", params: event.to_json, headers: headers
expect(response).to have_http_status(200) # This fails
end
end
context "an invalid signature" do
it "returns 401" do
post "/web_hooks/stripe", params: { type: "not_implemented" }
expect(response).to have_http_status(401)
end
end
end
module StripeTestHelper
def stripe_event_signature(payload)
time = Time.now
secret = Rails.application.credentials.stripe[:signing_secret]
signature = Stripe::Webhook::Signature.compute_signature(time, payload, secret)
Stripe::Webhook::Signature.generate_header(
time,
signature,
scheme: Stripe::Webhook::Signature::EXPECTED_SCHEME
)
end
end
Upvotes: 1
Views: 2557
Reputation: 1
Double-check your webhook signing secret, must start with a whsec_...
Upvotes: 0
Reputation: 1201
There are a couple reasons as to why you might be getting this, Stripe::SignatureVerificationError
error. The first being that a wrong value for your webhook signing secret, which would look something like whsec_
, was used. You can retrieve the correct one from your Dashboard by clicking on ‘Reveal’.
If you've confirmed that you've used the right secret, then the issue might be on the payload's content which likely is the issue here. This answer on another SO talks about this in depth. The summary is that Rails for Ruby will tamper with the raw payload and if it's not identical to what Stripe sent you, the signature won't be a match.
As for next steps, you'd want try request.raw_post
or find a similar solution to get to the exact raw JSON sent to you.
Upvotes: 3