Class: Assinafy::Support::WebhookVerifier
- Inherits:
-
Object
- Object
- Assinafy::Support::WebhookVerifier
- Defined in:
- lib/assinafy/support/webhook_verifier.rb
Overview
Defensive helper for verifying webhook deliveries when your gateway or proxy signs the body with an HMAC-SHA256 secret.
The Assinafy v1 API itself does not currently document a request-signing scheme for webhook deliveries, so this class is opt-in: construct it with a secret only if you have one configured in front of your webhook receiver (e.g. via API Gateway / Cloudflare). HMAC verifies authenticity, not freshness; the receiver must separately reject replayed event IDs or enforce its gateway's timestamp policy.
Instance Method Summary collapse
-
#event_data(event) ⇒ Hash
deprecated
Deprecated.
Prefer #event_payload (event params) and #event_object (acted-on entity). The Assinafy envelope has no top-level
datakey; this returnspayloadand falls back toobjectfor convenience. -
#event_object(event) ⇒ Hash
The entity the event acted on (the documented top-level
object), e.g. -
#event_payload(event) ⇒ Hash?
The event-specific data snapshot (the documented top-level
payload). -
#event_subject(event) ⇒ Hash
The actor that triggered the event (the documented top-level
subject), e.g. -
#event_type(event) ⇒ String?
Pull the event-type code from a parsed event Hash.
-
#extract_event(payload) ⇒ Hash?
Parse a JSON webhook body into a Hash, returning nil on malformed or non-object payloads.
-
#initialize(webhook_secret = nil) ⇒ WebhookVerifier
constructor
A new instance of WebhookVerifier.
-
#verify(payload, signature) ⇒ Boolean
Constant-time compare the provided signature to the expected HMAC-SHA256 of the raw payload.
Constructor Details
#initialize(webhook_secret = nil) ⇒ WebhookVerifier
Returns a new instance of WebhookVerifier.
33 34 35 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 33 def initialize(webhook_secret = nil) @webhook_secret = webhook_secret end |
Instance Method Details
#event_data(event) ⇒ Hash
Prefer #event_payload (event params) and #event_object
(acted-on entity). The Assinafy envelope has no top-level data key;
this returns payload and falls back to object for convenience.
122 123 124 125 126 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 122 def event_data(event) return {} unless event.is_a?(Hash) event['payload'] || event['object'] || {} end |
#event_object(event) ⇒ Hash
The entity the event acted on (the documented top-level object),
e.g. the Document. Includes a type discriminator.
99 100 101 102 103 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 99 def event_object(event) return {} unless event.is_a?(Hash) event['object'] || {} end |
#event_payload(event) ⇒ Hash?
The event-specific data snapshot (the documented top-level payload).
May be nil for events that carry no extra params (e.g.
document_uploaded).
88 89 90 91 92 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 88 def event_payload(event) return nil unless event.is_a?(Hash) event['payload'] end |
#event_subject(event) ⇒ Hash
The actor that triggered the event (the documented top-level subject),
e.g. the User. Includes a type discriminator.
110 111 112 113 114 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 110 def event_subject(event) return {} unless event.is_a?(Hash) event['subject'] || {} end |
#event_type(event) ⇒ String?
Pull the event-type code from a parsed event Hash. The canonical key in
the Assinafy v1 delivery envelope is event (e.g. assignment_created).
76 77 78 79 80 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 76 def event_type(event) return nil unless event.is_a?(Hash) event['event'] end |
#extract_event(payload) ⇒ Hash?
Parse a JSON webhook body into a Hash, returning nil on malformed or non-object payloads.
61 62 63 64 65 66 67 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 61 def extract_event(payload) text = payload.is_a?(String) ? payload : payload.to_s parsed = JSON.parse(text) parsed.is_a?(Hash) ? parsed : nil rescue JSON::ParserError nil end |
#verify(payload, signature) ⇒ Boolean
Constant-time compare the provided signature to the expected HMAC-SHA256 of the raw payload.
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/assinafy/support/webhook_verifier.rb', line 43 def verify(payload, signature) return false unless @webhook_secret && !@webhook_secret.empty? return false unless signature && !signature.to_s.strip.empty? body = payload.is_a?(String) ? payload : payload.to_s expected = OpenSSL::HMAC.hexdigest('SHA256', @webhook_secret, body) provided = signature.to_s.strip OpenSSL.fixed_length_secure_compare(expected, provided) rescue StandardError false end |