philiprehberger-webhook_builder 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +21 -0
- data/lib/philiprehberger/webhook_builder/client.rb +16 -0
- data/lib/philiprehberger/webhook_builder/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7754a65fd17d3f711872d837db0a95670d245eab1da96df4d42c723b8d7f9f3d
|
|
4
|
+
data.tar.gz: 8be04c1b22974980e572ca5073279d995f6e8f67d8853742de62297e5951a532
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f756201c37028a4f44d5975200d24fb811d87ecbc13467b9a9f3e5c792333c26dc546177871b9bda42d4bef3da1093202aa5f82279622521bf5c443d4fe61f8
|
|
7
|
+
data.tar.gz: c09e9a31e51d343140eb0beaa1db83560bd7a35dca976f00332534a888ece0eb8263a9701a6b5bf14720388ad381245b44b089689700fa0298ff9a5b16130742
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-04-18
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `Client#verify_signature(body:, signature:)` — constant-time HMAC-SHA256 comparison for the receiving side; returns `false` (never raises) on length mismatch
|
|
14
|
+
|
|
10
15
|
## [0.2.2] - 2026-04-15
|
|
11
16
|
|
|
12
17
|
### Changed
|
data/README.md
CHANGED
|
@@ -114,6 +114,26 @@ client.deliver(
|
|
|
114
114
|
)
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
### Verifying signatures
|
|
118
|
+
|
|
119
|
+
On the receiving side, use the same secret to verify the signature sent in the
|
|
120
|
+
`X-Webhook-Signature` header. The comparison is constant-time and will never
|
|
121
|
+
raise on malformed input.
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
require "philiprehberger/webhook_builder"
|
|
125
|
+
|
|
126
|
+
secret = "shared-signing-secret"
|
|
127
|
+
sender = Philiprehberger::WebhookBuilder.new(url: "https://example.com/webhooks", secret: secret)
|
|
128
|
+
receiver = Philiprehberger::WebhookBuilder.new(url: "https://example.com/webhooks", secret: secret)
|
|
129
|
+
|
|
130
|
+
body = '{"event":"order.created","payload":{"id":1}}'
|
|
131
|
+
signature = OpenSSL::HMAC.hexdigest("SHA256", secret, body)
|
|
132
|
+
|
|
133
|
+
receiver.verify_signature(body: body, signature: signature) # => true
|
|
134
|
+
receiver.verify_signature(body: body, signature: "tampered") # => false
|
|
135
|
+
```
|
|
136
|
+
|
|
117
137
|
### Delivery Tracking
|
|
118
138
|
|
|
119
139
|
```ruby
|
|
@@ -143,6 +163,7 @@ delivery.error # => nil or error message
|
|
|
143
163
|
| `.new(url:, secret:, timeout:, max_retries:, backoff:, concurrency:, default_headers:)` | Create a webhook client |
|
|
144
164
|
| `#deliver(event:, payload:, headers:)` | Deliver a webhook event and return a Delivery |
|
|
145
165
|
| `#deliver_batch(events)` | Deliver multiple events concurrently and return an array of Delivery results |
|
|
166
|
+
| `#verify_signature(body:, signature:)` | Constant-time HMAC-SHA256 verification of an incoming signature; returns `true`/`false` and never raises |
|
|
146
167
|
|
|
147
168
|
### `Delivery`
|
|
148
169
|
|
|
@@ -137,6 +137,22 @@ module Philiprehberger
|
|
|
137
137
|
results
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
+
# Verify an HMAC-SHA256 signature against a raw request body.
|
|
141
|
+
#
|
|
142
|
+
# Uses a constant-time comparison to resist timing attacks. Returns
|
|
143
|
+
# +false+ (never raises) when the provided signature has a different
|
|
144
|
+
# length than the expected hex digest.
|
|
145
|
+
#
|
|
146
|
+
# @param body [String] the raw request body
|
|
147
|
+
# @param signature [String] the hex-encoded signature to verify
|
|
148
|
+
# @return [Boolean] true when the signature matches, false otherwise
|
|
149
|
+
def verify_signature(body:, signature:)
|
|
150
|
+
expected = sign(body)
|
|
151
|
+
return false unless signature.is_a?(String) && signature.bytesize == expected.bytesize
|
|
152
|
+
|
|
153
|
+
OpenSSL.fixed_length_secure_compare(expected, signature)
|
|
154
|
+
end
|
|
155
|
+
|
|
140
156
|
private
|
|
141
157
|
|
|
142
158
|
# Sign the request body with HMAC-SHA256.
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-webhook_builder
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A webhook delivery client that signs payloads with HMAC-SHA256, retries
|
|
14
14
|
failed deliveries with configurable backoff strategies, supports batch delivery,
|