New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webhook Signature Verification #90
Webhook Signature Verification #90
Conversation
2 similar comments
Let's keep things focused. Please don't remove or or change the behavior of the |
Sounds good. Had only included it in this PR cause the original issue mentioned that Need to get the specs running locally so I can add some for this feature. Was having bundler version issues when I tried to run them initially. |
546e454
to
d2dbb83
Compare
This configuration value is used to verify the cryptographic signature of a Stripe webhook. This commit also updates the webhook controller to verify the signature. See Stripe for more details: https://stripe.com/docs/webhooks#signatures
d2dbb83
to
4b59c76
Compare
Thanks for making the adjustments to this PR. Looks clean. Have you tried this branch against a live Stripe endpoint yet? My only critique is that I'd prefer the tests to pass an actual HMAC signature header instead of mocking the call to I can merge and release a new version later today if no one else objects. Good work @mikeycgto! |
Thanks! Yeah I do agree with you and prefer to avoid mocking when possible. My concern there was the specs would become to specific to actual the HMAC implementation in Stripe. Figured mocks would just be quicker to write and more future-proof if their verification process changes (assuming the API doesn't change 😃). |
@rmm5t @mikeycgto Nice! I'd +1 trying to go a level deeper than the mock if possible. What you can do in this case is to call That way you can test more deeply than the mock and you don't have to rely on any particular crypto implementation — if we update to something beyond HMAC-SHA256, we'll be updating |
@brandur this was more involved than I thought it would be (have to include a timestamp and version scheme). I do agree it's better to use real signatures here though. Thanks for the feedback! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Left a couple comments below.
(BTW, just so it's clear, I don't have any direct involvement in this project, and just took a look because a related thread had been bumped with this PR. I fully defer to the real maintainers on all things.)
after(:each) { StripeEvent.signing_secret = nil } | ||
|
||
it "rejects invalid signatures" do | ||
webhook_with_signature generate_signature('invalid payload'), id: 'evt_charge_succeeded' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I don't think I fully understand this test. Why does this one come out as invalid with the one below valid? It seems that it should be computing a valid signature for any value that you send to #generate_signature
shouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps I shouldn't use generate_signature
? I wanted to have a spec that passes the correct format with the timestamp but with an incorrect signature. Maybe I should just pass a string directly here like so:
webhook_with_signature "t=#{timestamp},v1=invalid", id: 'evt_charge_succeeded'
Perhaps a better spec would be to "reject missing signature"
where no header is provided? Any suggestions here @rmm5t?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest just passing in a "bogus" signature string and avoid the call to generate_signature
.
end | ||
|
||
let(:secret) { 'secret' } | ||
let(:signature) { 'signature' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be unused now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed 😄
end | ||
|
||
def generate_signature(payload) | ||
signature = Stripe::Webhook::Signature.send(:compute_signature, "#{timestamp}.#{payload}", secret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shoot. I forgot this is declared private. Sorry about that! I expect this to be pretty stable, but we might want to consider exposing this publicly for testing purposes if nothing else.
Refactored the specs some to hopefully make more sense. Thanks again for the feedback! |
2 similar comments
8b53943
to
01ffaa8
Compare
@mikeycgto Looks good to me. Are you done with your refactoring? I'm happy to merge now when ready. |
I'm good with merging. Thanks. |
Closes #83.
This to do for this PR: