Module: HighLevel::Webhooks
- Defined in:
- lib/high_level/webhooks.rb
Overview
Verifies inbound HighLevel webhook signatures.
HighLevel signs webhook payloads with the platform’s private key and publishes the corresponding public key. Verification is therefore asymmetric — the ‘public_key:` argument is the published PEM key, not a shared secret.
Two schemes are supported:
:rsa — RSA-SHA256. Signature arrives on `x-wh-signature`.
:ed25519 — Ed25519. Signature arrives on `x-ghl-signature`.
Both signatures are base64-encoded. The payload is the raw JSON body of the request as bytes — do not re-serialize via your framework’s parser (round-tripping changes the canonical form).
Source: vendor/highlevel-api-sdk/lib/webhook/webhook-manager.ts (verifySignature + verifyEd25519Signature) cross-checked with the published HighLevel webhook docs.
Defined Under Namespace
Classes: InvalidSignatureError
Constant Summary collapse
- SCHEMES =
The supported signature schemes.
%i[rsa ed25519].freeze
Class Method Summary collapse
-
.verify(payload:, signature:, public_key:, scheme: :rsa) ⇒ Object
Verify a webhook signature.
Class Method Details
.verify(payload:, signature:, public_key:, scheme: :rsa) ⇒ Object
Verify a webhook signature. Returns true on success; raises InvalidSignatureError on any failure mode (bad signature, wrong key, malformed base64, missing inputs). Caller-supplied ArgumentError for invalid scheme. rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/high_level/webhooks.rb', line 38 def self.verify(payload:, signature:, public_key:, scheme: :rsa) raise ArgumentError, "scheme must be one of: #{SCHEMES.join(", ")}" unless SCHEMES.include?(scheme) raise InvalidSignatureError, "signature is required" if signature.nil? || signature.to_s.empty? raise InvalidSignatureError, "public_key is required" if public_key.nil? || public_key.to_s.empty? signature_bytes = decode_signature(signature) key = load_key(public_key) valid = verify_for(scheme, key, signature_bytes, payload.to_s) raise InvalidSignatureError, "signature does not match payload" unless valid true rescue OpenSSL::OpenSSLError => e raise InvalidSignatureError, "openssl error: #{e.}" end |