Skip to main content
Version: Latest

11. Security

11.1 Webhook Signature Verification

Every inbound webhook POST is authenticated by HMAC-SHA256 over the raw request body, keyed by WhatsAppCloudApiOptions.AppSecret, compared with CryptographicOperations.FixedTimeEquals (constant-time, resistant to timing side-channel attacks). This is the only authentication mechanism for the webhook endpoint, since it is [AllowAnonymous] by necessity — see §8.3.

SignatureValidationEnabled (default true) must never be disabled in production. Disabling it means any party who discovers the webhook URL can inject arbitrary "inbound messages" and "status updates" into the Inbox system and the Notification Framework's delivery-receipt pipeline.

11.2 Token Handling

  • AccessToken (platform) and tenant-scoped WhatsAppOperationalSettings.AccessToken are long-lived Meta Cloud API tokens — treated as secrets, sourced from environment variables in production (WhatsAppCloudApi__AccessToken), never committed to source control or appsettings.json directly.
  • Tokens are never included in any API response, log line, or CommunicationHistory/TenantNotificationLog record.
  • Rotation is supported (SecretsManifest marks AccessToken and VerifyToken as SupportsRotation: true) — rotating requires updating the environment variable and restarting/reconfiguring the app; there is no hot-reload of these values mid-process beyond the standard IOptionsMonitor behavior already provided by the configuration system.

11.3 Secret Handling

Five secrets are declared in SecretsManifest (see §4.2): VerifyToken, AppSecret, AccessToken, PhoneNumberId, BusinessAccountId. All are ProductionRequired: trueSecretsHealthCheck flags a missing value as a startup warning in Production. None of these values, nor the tenant-scoped equivalents in WhatsAppOperationalSettings, are ever logged, including in LogRawPayload debug mode (which logs the payload, not the configured secrets used to validate it).

11.4 Permission Gates

Every endpoint except the two webhook actions requires both authentication ([Authorize], implied by [MustHavePermission]) and a specific permission — see the full per-endpoint table in §6 API Reference. Two permission families exist: PermissionConstants.WhatsApp.* (manual test endpoints only) and PermissionConstants.WhatsAppInbox.* (the Inbox system). A tenant admin should scope agent roles to only the Inbox permissions their support team actually needs — WhatsAppInbox.ViewAll in particular grants visibility into every agent's conversations, not just the caller's own.

11.5 Diagnostic Endpoint Risks

CommunicationDiagnosticsController (see §6.9) exposes detailed configuration and resolution-decision information, and one endpoint (SmokeTest/WhatsApp) sends a real WhatsApp message to whatever toPhone is supplied. Treat this controller as admin/support-tier only:

  • GET Health and GET Diagnostics/* reveal whether credentials are configured (not their values), template resolution decisions, and configuration warnings — useful to an attacker for reconnaissance if exposed too broadly.
  • POST SmokeTest/WhatsApp performs a real Meta API call and a real template dispatch — restrict the Communications.SmokeTest permission tightly, and never point it at a production customer's phone number during testing.
  • None of these endpoints require anything beyond the platform's standard [MustHavePermission] gate — there is no additional rate-limiting or IP-allowlisting layer specific to diagnostics. If broader exposure is needed (e.g. a support portal), add that control at the gateway/reverse-proxy layer, not by weakening these permissions.

11.6 Production Safety Notes

  • LogRawPayload must stay false in production — raw webhook JSON can contain customer message content.
  • SignatureValidationEnabled must stay true in production.
  • The Meta CDN media URL is never exposed to a frontend client (see §10.6) — always proxy media downloads through the backend.
  • Test/diagnostic endpoints that perform real Meta API calls (WhatsAppController's four test endpoints, CommunicationController.Test/WhatsApp, CommunicationDiagnosticsController.SmokeTest/WhatsApp) should be restricted to admin/support roles and never wired into any customer-facing UI flow.