huskies: merge 807
This commit is contained in:
@@ -12,6 +12,7 @@ pub mod format;
|
||||
pub mod history;
|
||||
pub mod meta;
|
||||
pub mod twilio;
|
||||
pub mod verify;
|
||||
|
||||
pub use history::{MessagingWindowTracker, WhatsAppConversationHistory, load_whatsapp_history};
|
||||
pub use meta::WhatsAppTransport;
|
||||
@@ -121,6 +122,10 @@ pub struct WhatsAppWebhookContext {
|
||||
/// Phone numbers allowed to send messages to the bot.
|
||||
/// When empty, all numbers are allowed (backwards compatible).
|
||||
pub allowed_phones: Vec<String>,
|
||||
/// Meta app secret for `X-Hub-Signature-256` HMAC verification.
|
||||
/// When non-empty, every inbound POST is verified against this secret.
|
||||
/// When empty, signature verification is skipped.
|
||||
pub app_secret: String,
|
||||
}
|
||||
|
||||
/// GET /webhook/whatsapp — webhook verification.
|
||||
@@ -158,13 +163,16 @@ pub async fn webhook_verify(
|
||||
/// - `"twilio"`: parses Twilio's `application/x-www-form-urlencoded` body.
|
||||
///
|
||||
/// Both providers expect a `200 OK` response, even on parse errors.
|
||||
///
|
||||
/// For the `"meta"` provider, the `X-Hub-Signature-256` header is verified
|
||||
/// against the configured app secret (HMAC-SHA256). Requests with a missing
|
||||
/// or invalid signature are rejected with `401`/`403` respectively.
|
||||
#[handler]
|
||||
pub async fn webhook_receive(
|
||||
req: &Request,
|
||||
body: poem::Body,
|
||||
ctx: poem::web::Data<&Arc<WhatsAppWebhookContext>>,
|
||||
) -> Response {
|
||||
let _ = req;
|
||||
let bytes = match body.into_bytes().await {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
@@ -175,6 +183,23 @@ pub async fn webhook_receive(
|
||||
}
|
||||
};
|
||||
|
||||
// Verify HMAC-SHA256 signature for Meta webhooks when an app secret is configured.
|
||||
if ctx.provider != "twilio" && !ctx.app_secret.is_empty() {
|
||||
let signature = req.header("X-Hub-Signature-256").unwrap_or("");
|
||||
if signature.is_empty() {
|
||||
slog!("[whatsapp] Missing X-Hub-Signature-256 header; rejecting request");
|
||||
return Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body("Missing signature");
|
||||
}
|
||||
if !verify::verify_meta_signature(&ctx.app_secret, &bytes, signature) {
|
||||
slog!("[whatsapp] X-Hub-Signature-256 verification failed; rejecting request");
|
||||
return Response::builder()
|
||||
.status(StatusCode::FORBIDDEN)
|
||||
.body("Invalid signature");
|
||||
}
|
||||
}
|
||||
|
||||
let messages = if ctx.provider == "twilio" {
|
||||
let msgs = extract_twilio_text_messages(&bytes);
|
||||
if msgs.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user