Skip to content

fix: sync webhook events and HMAC verification with OpenWA v0.4.0#2

Merged
rmyndharis merged 3 commits into
mainfrom
fix/openwa-v0.4.0-sync
Jun 18, 2026
Merged

fix: sync webhook events and HMAC verification with OpenWA v0.4.0#2
rmyndharis merged 3 commits into
mainfrom
fix/openwa-v0.4.0-sync

Conversation

@rmyndharis

@rmyndharis rmyndharis commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

Brings the node back in sync with the OpenWA backend (verified against v0.4.0). Fixes the two defects tracked in #1, refreshes documentation for payload drift, and adds a unit test for signature verification.

Defect 1 — Invalid webhook event names (HTTP 400 on trigger activation)

session.connected and session.qr_ready are not in OpenWA's accepted WEBHOOK_EVENTS set, so selecting them made POST /api/sessions/:id/webhooks return 400. Both nodes now offer the canonical 12-event set and the two invalid values are removed:

message.received, message.sent, message.ack, message.failed, message.revoked,
session.status, session.qr, session.authenticated, session.disconnected,
group.join, group.leave, group.update

Defect 2 — Webhook secret / HMAC mismatch (silent drop)

The Trigger previously posted only { url, events } on creation and verified a plaintext x-webhook-secret header that OpenWA never sends, so every delivery was dropped when a secret was configured. Now:

  • create() registers the secret with OpenWA, and
  • webhook() verifies the X-OpenWA-Signature: sha256=<hex> HMAC-SHA256 over the raw request body (timing-safe), rejecting failed verification with HTTP 401.

The secret is registered and verified with the same value, so both sides stay in sync by construction. Verification hashes the raw bytes (not a re-serialized body), matching the exact JSON.stringify(payload) OpenWA signs.

Additional: webhook secret on the action node

The action node's Create Webhook operation gains an optional Webhook Secret field, included in the create body so OpenWA signs deliveries to webhooks registered through the action node — mirroring the Trigger's secret handling. (Originally noted as out of scope in #1; added on request.)

Documentation

  • README: events table, data.id (not messageId) for incoming payloads, engine-neutral message type (chat→text, ptt→voice, vcard→contact), engine-canonical whatsappId from contact checks, and an "OpenWA >= 0.2.8" compatibility note.

Tests

  • New node:test suite (test/verifySignature.test.mjs) covering valid, tampered-body, wrong-secret, missing-header, empty-header, and malformed-prefix cases — no new dependencies.
  • CI runs the suite after build.

Verification

npm run lint, npm run build, and the test suite (7/7) all pass locally. The action node's REST endpoints were confirmed unchanged in v0.4.0 and are untouched.

Closes #1

- Replace invalid webhook event values (session.connected, session.qr_ready)
  with the canonical names and add the full WEBHOOK_EVENTS set in both nodes
- Register the webhook secret on creation and verify the X-OpenWA-Signature
  HMAC-SHA256 header over the raw request body (was a plaintext header check)
- Reject failed signature verification with HTTP 401
- Refresh README for payload drift (data.id, neutral type, whatsappId) and add
  an OpenWA >= 0.2.8 compatibility note
- Add a node:test unit suite for signature verification and run it in CI

Closes #1
…ation

Adds an optional Webhook Secret field to the OpenWA action node's Create
Webhook operation and includes it in the create request body, so OpenWA signs
deliveries to webhooks registered through the action node. Mirrors the Trigger
node's secret handling (the secret is sent verbatim, not trimmed).
@rmyndharis rmyndharis merged commit 78ebaf7 into main Jun 18, 2026
1 check passed
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.

Sync node with OpenWA v0.4.0: invalid webhook events (400) + webhook HMAC verification (silent drop)

1 participant