/
webhook_test.rb
135 lines (120 loc) · 5.09 KB
/
webhook_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# frozen_string_literal: true
require ::File.expand_path("../test_helper", __dir__)
module Stripe
class WebhookTest < Test::Unit::TestCase
EVENT_PAYLOAD = <<~PAYLOAD
{
"id": "evt_test_webhook",
"object": "event"
}
PAYLOAD
SECRET = "whsec_test_secret"
def generate_header(opts = {})
opts[:timestamp] ||= Time.now
opts[:payload] ||= EVENT_PAYLOAD
opts[:secret] ||= SECRET
opts[:scheme] ||= Stripe::Webhook::Signature::EXPECTED_SCHEME
opts[:signature] ||= Stripe::Webhook::Signature.compute_signature(
opts[:timestamp],
opts[:payload],
opts[:secret]
)
Stripe::Webhook::Signature.generate_header(
opts[:timestamp],
opts[:signature],
scheme: opts[:scheme]
)
end
context ".compute_signature" do
should "compute a signature which can then be verified" do
timestamp = Time.now
signature = Stripe::Webhook::Signature.compute_signature(
timestamp,
EVENT_PAYLOAD,
SECRET
)
header = generate_header(timestamp: timestamp, signature: signature)
assert(Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, SECRET))
end
end
context ".generate_header" do
should "generate a header in valid format" do
timestamp = Time.now
signature = Stripe::Webhook::Signature.compute_signature(
timestamp,
EVENT_PAYLOAD,
SECRET
)
scheme = "v1"
header = Stripe::Webhook::Signature.generate_header(
timestamp,
signature,
scheme: scheme
)
assert_equal("t=#{timestamp.to_i},#{scheme}=#{signature}", header)
end
end
context ".construct_event" do
should "return an Event instance from a valid JSON payload and valid signature header" do
header = generate_header
event = Stripe::Webhook.construct_event(EVENT_PAYLOAD, header, SECRET)
assert event.is_a?(Stripe::Event)
end
should "raise a JSON::ParserError from an invalid JSON payload" do
assert_raises JSON::ParserError do
payload = "this is not valid JSON"
header = generate_header(payload: payload)
Stripe::Webhook.construct_event(payload, header, SECRET)
end
end
should "raise a SignatureVerificationError from a valid JSON payload and an invalid signature header" do
header = "bad_header"
assert_raises Stripe::SignatureVerificationError do
Stripe::Webhook.construct_event(EVENT_PAYLOAD, header, SECRET)
end
end
end
context ".verify_signature_header" do
should "raise a SignatureVerificationError when the header does not have the expected format" do
header = "i'm not even a real signature header"
e = assert_raises(Stripe::SignatureVerificationError) do
Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, "secret")
end
assert_match("Unable to extract timestamp and signatures from header", e.message)
end
should "raise a SignatureVerificationError when there are no signatures with the expected scheme" do
header = generate_header(scheme: "v0")
e = assert_raises(Stripe::SignatureVerificationError) do
Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, "secret")
end
assert_match("No signatures found with expected scheme", e.message)
end
should "raise a SignatureVerificationError when there are no valid signatures for the payload" do
header = generate_header(signature: "bad_signature")
e = assert_raises(Stripe::SignatureVerificationError) do
Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, "secret")
end
assert_match("No signatures found matching the expected signature for payload", e.message)
end
should "raise a SignatureVerificationError when the timestamp is not within the tolerance" do
header = generate_header(timestamp: Time.now - 15)
e = assert_raises(Stripe::SignatureVerificationError) do
Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, SECRET, tolerance: 10)
end
assert_match("Timestamp outside the tolerance zone", e.message)
end
should "return true when the header contains a valid signature and the timestamp is within the tolerance" do
header = generate_header
assert(Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, SECRET, tolerance: 10))
end
should "return true when the header contains at least one valid signature" do
header = generate_header + ",v1=bad_signature"
assert(Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, SECRET, tolerance: 10))
end
should "return true when the header contains a valid signature and the timestamp is off but no tolerance is provided" do
header = generate_header(timestamp: Time.at(12_345))
assert(Stripe::Webhook::Signature.verify_header(EVENT_PAYLOAD, header, SECRET))
end
end
end
end