Skip to content

MT-22022: Add webhook signature verification helper#110

Open
Rabsztok wants to merge 1 commit into
mainfrom
MT-22022-webhook-signature-verification
Open

MT-22022: Add webhook signature verification helper#110
Rabsztok wants to merge 1 commit into
mainfrom
MT-22022-webhook-signature-verification

Conversation

@Rabsztok
Copy link
Copy Markdown

@Rabsztok Rabsztok commented May 20, 2026

Motivation

Follow-up to mailtrap-ruby#108 review comment: expose a helper so users don't have to re-implement Mailtrap's HMAC-SHA256 webhook signature check on every receiver.

Changes

  • Mailtrap::Webhooks.verify_signature(payload:, signature:, signing_secret:)true/false. HMAC-SHA256 over the raw body, constant-time compare via OpenSSL.fixed_length_secure_compare. Returns false (never raises) on empty / wrong-length / non-hex / non-string inputs.
  • spec/mailtrap/webhooks_spec.rb pins a cross-SDK fixture (payload + signing_secret + expected digest) shared verbatim across all six official Mailtrap SDKs to guarantee byte-for-byte parity.
  • examples/webhooks_signature_verification.rb — runnable usage snippet.
  • README — new "Verifying webhook signatures" subsection.

How to test

CI runs the full spec suite and lint. Manually:

bundle exec ruby examples/webhooks_signature_verification.rb

The script should exit 0 with no output.

Companion PRs

Coordinated rollout across all six official SDKs (same algorithm, same shared fixture):

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

📝 Walkthrough

Walkthrough

This PR adds webhook signature verification to the Mailtrap Ruby gem. A new Mailtrap::Webhooks module provides verify_signature to validate HMAC-SHA256 signatures using constant-time comparison. The feature includes comprehensive RSpec tests, a Rack-compatible receiver example, and documentation showing how to verify Mailtrap-Signature headers against raw request bodies.

Changes

Webhook Signature Verification

Layer / File(s) Summary
Webhook signature verification module
lib/mailtrap/webhooks.rb, lib/mailtrap.rb
Mailtrap::Webhooks module with verify_signature(payload:, signature:, signing_secret:) validates HMAC-SHA256 using OpenSSL::HMAC.hexdigest and constant-time comparison via OpenSSL.fixed_length_secure_compare, returning false for invalid inputs instead of raising. The module is required in the gem's main entry point.
Signature verification test suite
spec/mailtrap/webhooks_spec.rb
RSpec tests define cross-SDK fixtures and validate verify_signature against correct signatures, wrong secrets, tampered payloads, invalid lengths, non-hex content, and empty inputs. A cross-SDK fixture test recomputes the HMAC-SHA256 digest to assert both digest equality and method behavior.
Webhook receiver example and documentation
examples/webhooks_signature_verification.rb, README.md
Example code shows a Rack-compatible receiver that verifies signatures before parsing payloads and returns 401 on failure, plus direct-verification snippets demonstrating safe handling of invalid inputs. README adds a "Verifying webhook signatures" section documenting HMAC-SHA256 behavior, updates the supported-functionality list, adjusts formatting, and removes trailing whitespace.

Sequence Diagram

sequenceDiagram
  participant Client as Webhook Client
  participant Receiver as WebhookReceiver
  participant Verify as Mailtrap::Webhooks
  participant OpenSSL as OpenSSL::HMAC
  participant Compare as fixed_length_secure_compare
  Client->>Receiver: POST raw_body + Mailtrap-Signature header
  Receiver->>Verify: verify_signature(raw_body, signature, secret)
  Verify->>OpenSSL: hexdigest(secret, raw_body)
  OpenSSL-->>Verify: expected_hex
  Verify->>Compare: fixed_length_secure_compare(expected, signature)
  alt Signature matches
    Compare-->>Verify: true
    Verify-->>Receiver: true
    Receiver->>Receiver: parse JSON payload
    Receiver-->>Client: 200 OK
  else Signature invalid
    Compare-->>Verify: false or ArgumentError
    Verify-->>Receiver: false
    Receiver-->>Client: 401 Unauthorized
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • IgorDobryn
  • DagonWat
  • mklocek

Poem

🐰 A signature arrives at the door,
We hash and compare, then check once more,
With constant-time guards and OpenSSL's might,
Each webhook is verified, tight and right! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adding a webhook signature verification helper, and references the Jira ticket MT-22022.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description comprehensively documents motivation, implementation details, testing instructions, and coordinated companion work across SDKs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch MT-22022-webhook-signature-verification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/webhooks_signature_verification.rb`:
- Around line 1-2: Add explicit requires for Rack and JSON at the top of the
example: include require 'rack' and require 'json' alongside the existing
require 'mailtrap' so that Rack::Request and JSON.parse are defined when running
the standalone script (this affects the usage sites of Rack::Request and
JSON.parse in the file).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f503201f-688f-4346-89a4-536e35b0c132

📥 Commits

Reviewing files that changed from the base of the PR and between 1102ed9 and 2c0513e.

📒 Files selected for processing (5)
  • README.md
  • examples/webhooks_signature_verification.rb
  • lib/mailtrap.rb
  • lib/mailtrap/webhooks.rb
  • spec/mailtrap/webhooks_spec.rb

Comment thread examples/webhooks_signature_verification.rb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant