Skip to content

fix(channels): wire Teams inbound through the generic webhook route - #121

Open
RameshHertzai wants to merge 1 commit into
mainfrom
fix/teams-inbound-webhook
Open

RameshHertzai wants to merge 1 commit into
mainfrom
fix/teams-inbound-webhook

Conversation

@RameshHertzai

Copy link
Copy Markdown
Contributor

Problem

Microsoft Teams had a working outbound path (BotFrameworkAdapter) but no inbound one — TeamsAdapter.process_activity() was never reached by any HTTP route. Teams could send but not receive: listed in the channel catalog, half-connected.

Bot Framework can't ride the existing generic webhook auth model as-is: it POSTs an Activity with a JWT in the Authorization header, not a Kong stamp or an HMAC-over-body signature, so the route's gate rejected it before the adapter ran.

Fix (kept generic — no Teams-specific branch in the route)

  • TeamsAdapter.handle_webhook(body, auth_header) — deserializes the Activity and hands it to process_activity(), which validates the JWT fail-closed. Sets webhook_self_authenticates = True.
  • Generic route (flask_integration.py) — an adapter that sets webhook_self_authenticates is True opts out of the Kong/HMAC gate (it authenticates itself), and the route now maps an auth_header/authorization param to the Authorization header. Strict identity check (is True) so a truthy stand-in can never silently disable the gate.

Any future bearer-JWT channel reuses the same seam — no new bespoke code.

Out of scope (deliberately)

WhatsApp is unchanged. Its Baileys gateway is a persistent WhatsApp-Web connection, not an HTTP webhook, so it can't be folded onto this path without breaking it — it stays a documented exception.

Tests

Adds two regression cases: (1) a self-authenticating adapter bypasses the gate and its handle_webhook receives the Authorization header; (2) a truthy-but-not-True flag must NOT bypass the gate. Full file: 25 passed.

Teams had a working outbound path (BotFrameworkAdapter) but no inbound: the
adapter's process_activity() was never reached by any HTTP route, so Teams
could send but not receive — listed in the catalog, half-connected.

Bot Framework can't ride the existing generic webhook auth model: it posts an
Activity with a JWT in the Authorization header, not a Kong stamp or an
HMAC-over-body signature, so the gate rejected it before the adapter ran.

Fix, kept generic (no Teams-specific branch in the route):
- TeamsAdapter.handle_webhook(body, auth_header): deserialize the Activity and
  hand it to process_activity(), which validates the JWT fail-closed. Sets
  webhook_self_authenticates = True.
- Generic route: an adapter that sets webhook_self_authenticates is True opts
  out of the Kong/HMAC gate (it authenticates itself), and the route now maps
  an auth_header/authorization param to the Authorization header. Strict
  identity check (is True) so a truthy stand-in can never silently disable the
  gate.

Any future bearer-JWT channel reuses the same seam. WhatsApp is unchanged —
its Baileys gateway is a persistent connection, not a webhook, so it stays a
documented exception rather than being forced onto this path.

Tests: adds two cases (self-auth bypass + auth-header delivery; truthy-but-not-
True must NOT bypass). Full file 25 passed.
@RameshHertzai
RameshHertzai requested a review from a team September 15, 2026 10:10
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