openclaw - 💡(How to fix) Fix msteams: v2026.4.26 ships broken JWT validator (jwt.verify is not a function); fix b3bc60ae missed the cut [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#73754Fetched 2026-04-29 06:15:32
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
0
Author
Timeline (top)
commented ×1mentioned ×1subscribed ×1

The msteams plugin bundled with [email protected] (which pins @openclaw/[email protected]) silently drops every inbound Teams message because jwt.verify is not a function. Outbound messages from the bot continue to work, masking the failure — bots appear "online" but never receive user messages.

A fix has already landed on main in commit b3bc60ae40 ("fix(msteams): unwrap jwt runtime deps", 2026-04-27 20:53 UTC), but it was not included in the v2026.4.26 release which was cut a few hours later. So users upgrading to v2026.4.26 still hit this regression.

Error Message

[MSTEAMS_DIAG] inbound POST /api/messages ua=Microsoft-SkypeBotApi (Microsoft-BotFramework/3.0) [MSTEAMS_DIAG] JWT header={"alg":"RS256","kid":"Pr1J4k5mkxHV31woViVQirfzm5s","typ":"JWT"} [MSTEAMS_DIAG] JWT claims iss=https://api.botframework.com aud=<our appId> serviceurl=https://smba.trafficmanager.net/amer/<tenant>/ exp=… (valid) [JWT_DIAG] resolving kid=… from https://login.botframework.com/v1/.well-known/keys [JWT_DIAG] got public key, length=450 [JWT_DIAG] EXCEPTION during verify: name=TypeError message=jwt.verify is not a function [MSTEAMS_DIAG] JWT validation FAILED (returned falsy)

Root Cause

In the compiled bundle dist/extensions/msteams/graph-users-Bgd5K8gB.js:

// Compiled (broken):
botFrameworkJwtDepsPromise ??= Promise.all([import("jsonwebtoken"), import("jwks-rsa")])
  .then(([jwt, { JwksClient }]) => ({ jwt, JwksClient }));

jsonwebtoken is a CommonJS module. Dynamic import() of a CJS module in Node ESM yields a namespace where verify only exists on .default (while decode is also exposed on the namespace, which is why jwt.decode(token) succeeds and jwt.verify(...) throws TypeError: jwt.verify is not a function).

The try { ... } catch { return false; } in createBotFrameworkJwtValidator.validate then silently swallows the TypeError, returning a falsy validation result and 401-ing the request.

The TS source already has the safe wrappers (loadJsonwebtokenRuntime, loadJwksClientRuntime) introduced in b3bc60ae40, but the plugin shipped at @openclaw/[email protected] (bundled in [email protected]) was built before that commit landed, and the bundler appears to have inlined the destructure rather than calling the helpers.

Fix Action

Fix / Workaround

Expected: Bot receives the message and an agent reply is dispatched. Actual: Endpoint returns HTTP 401 silently, no agent run, no log output (even at logging.level=debug). Outbound from the bot still works, so the failure is invisible without packet/inbound instrumentation.

Diagnostic capture (what we observed)

With local instrumentation patches:

After this single-line fix, JWT validation passes, conversations register, agent runs dispatch, and replies flow back to Teams.

Code Example

// Compiled (broken):
botFrameworkJwtDepsPromise ??= Promise.all([import("jsonwebtoken"), import("jwks-rsa")])
  .then(([jwt, { JwksClient }]) => ({ jwt, JwksClient }));

---

[MSTEAMS_DIAG] inbound POST /api/messages ua=Microsoft-SkypeBotApi (Microsoft-BotFramework/3.0)
[MSTEAMS_DIAG] JWT header={"alg":"RS256","kid":"Pr1J4k5mkxHV31woViVQirfzm5s","typ":"JWT"}
[MSTEAMS_DIAG] JWT claims iss=https://api.botframework.com aud=<our appId> serviceurl=https://smba.trafficmanager.net/amer/<tenant>/ exp= (valid)
[JWT_DIAG] resolving kid=from https://login.botframework.com/v1/.well-known/keys
[JWT_DIAG] got public key, length=450
[JWT_DIAG] EXCEPTION during verify: name=TypeError message=jwt.verify is not a function
[MSTEAMS_DIAG] JWT validation FAILED (returned falsy)

---

// dist/extensions/msteams/graph-users-Bgd5K8gB.js
botFrameworkJwtDepsPromise ??= Promise.all([import("jsonwebtoken"), import("jwks-rsa")])
  .then(([jwtMod, { JwksClient }]) => ({
    jwt: jwtMod.default ?? jwtMod,
    JwksClient,
  }));
RAW_BUFFERClick to expand / collapse

Summary

The msteams plugin bundled with [email protected] (which pins @openclaw/[email protected]) silently drops every inbound Teams message because jwt.verify is not a function. Outbound messages from the bot continue to work, masking the failure — bots appear "online" but never receive user messages.

A fix has already landed on main in commit b3bc60ae40 ("fix(msteams): unwrap jwt runtime deps", 2026-04-27 20:53 UTC), but it was not included in the v2026.4.26 release which was cut a few hours later. So users upgrading to v2026.4.26 still hit this regression.

Reproduction

  1. Install [email protected] (bundles @openclaw/[email protected])
  2. Configure a fully working Bot Channels / Teams app with valid appId, appPassword, tenantId, public messaging endpoint
  3. Send any message to the bot in a Teams DM

Expected: Bot receives the message and an agent reply is dispatched. Actual: Endpoint returns HTTP 401 silently, no agent run, no log output (even at logging.level=debug). Outbound from the bot still works, so the failure is invisible without packet/inbound instrumentation.

Root cause

In the compiled bundle dist/extensions/msteams/graph-users-Bgd5K8gB.js:

// Compiled (broken):
botFrameworkJwtDepsPromise ??= Promise.all([import("jsonwebtoken"), import("jwks-rsa")])
  .then(([jwt, { JwksClient }]) => ({ jwt, JwksClient }));

jsonwebtoken is a CommonJS module. Dynamic import() of a CJS module in Node ESM yields a namespace where verify only exists on .default (while decode is also exposed on the namespace, which is why jwt.decode(token) succeeds and jwt.verify(...) throws TypeError: jwt.verify is not a function).

The try { ... } catch { return false; } in createBotFrameworkJwtValidator.validate then silently swallows the TypeError, returning a falsy validation result and 401-ing the request.

The TS source already has the safe wrappers (loadJsonwebtokenRuntime, loadJwksClientRuntime) introduced in b3bc60ae40, but the plugin shipped at @openclaw/[email protected] (bundled in [email protected]) was built before that commit landed, and the bundler appears to have inlined the destructure rather than calling the helpers.

Diagnostic capture (what we observed)

With local instrumentation patches:

[MSTEAMS_DIAG] inbound POST /api/messages ua=Microsoft-SkypeBotApi (Microsoft-BotFramework/3.0)
[MSTEAMS_DIAG] JWT header={"alg":"RS256","kid":"Pr1J4k5mkxHV31woViVQirfzm5s","typ":"JWT"}
[MSTEAMS_DIAG] JWT claims iss=https://api.botframework.com aud=<our appId> serviceurl=https://smba.trafficmanager.net/amer/<tenant>/ exp=… (valid)
[JWT_DIAG] resolving kid=… from https://login.botframework.com/v1/.well-known/keys
[JWT_DIAG] got public key, length=450
[JWT_DIAG] EXCEPTION during verify: name=TypeError message=jwt.verify is not a function
[MSTEAMS_DIAG] JWT validation FAILED (returned falsy)

Token claims are correct, JWKS fetch is correct, kid resolves, public key extraction works. The verify call itself throws.

Local hot-fix that restored two-way comms

// dist/extensions/msteams/graph-users-Bgd5K8gB.js
botFrameworkJwtDepsPromise ??= Promise.all([import("jsonwebtoken"), import("jwks-rsa")])
  .then(([jwtMod, { JwksClient }]) => ({
    jwt: jwtMod.default ?? jwtMod,
    JwksClient,
  }));

After this single-line fix, JWT validation passes, conversations register, agent runs dispatch, and replies flow back to Teams.

Severity

High for any 1:1 or group Teams use case. The failure is invisible (silent 401, no logs even at debug), and the bot looks healthy from the outside because outbound works. We hit ~12 days of dead inbound before pinpointing it.

Suggested actions

  1. Cut a v2026.4.27 (or v2026.4.26.1) that includes b3bc60ae40 and republishes @openclaw/msteams with the matching version bump.
  2. Consider upgrading the silent catch { return false; } in createBotFrameworkJwtValidator.validate to log the error at warn level — silent JWT validation failures are nearly impossible to diagnose without source patching.
  3. Add a JWT validation smoke test against a fixture token in CI to catch this regression.

Environment

  • openclaw: 2026.4.26
  • @openclaw/msteams: 2026.4.25
  • Node: v22.22.0
  • OS: Debian 13 (Linux 6.12.74+deb13+1-amd64)
  • Bot Framework: standard Microsoft Teams channel via Azure Bot resource (Single Tenant)

Happy to provide a PR for both the source-level guarantee that the bundler can't strip the wrappers, and the catch-block logging improvement, if it would help. Thanks for OpenClaw — once we got past this, two-way comms have been rock solid. 🦞

extent analysis

TL;DR

The most likely fix is to upgrade to a version of openclaw and @openclaw/msteams that includes the commit b3bc60ae40, which fixes the issue with jwt.verify not being a function.

Guidance

  • The issue is caused by the dynamic import of a CommonJS module (jsonwebtoken) in a Node ESM environment, which yields a namespace where verify only exists on .default.
  • To fix the issue, the botFrameworkJwtDepsPromise needs to be updated to correctly handle the namespace of the jsonwebtoken module.
  • A local hot-fix has been provided, which updates the botFrameworkJwtDepsPromise to correctly handle the namespace.
  • Consider logging the error at warn level in the createBotFrameworkJwtValidator.validate function to make it easier to diagnose similar issues in the future.

Example

The local hot-fix provided in the issue can be used as an example of how to update the botFrameworkJwtDepsPromise:

botFrameworkJwtDepsPromise ??= Promise.all([import("jsonwebtoken"), import("jwks-rsa")])
  .then(([jwtMod, { JwksClient }]) => ({
    jwt: jwtMod.default ?? jwtMod,
    JwksClient,
  }));

Notes

The issue is specific to the versions of openclaw and @openclaw/msteams mentioned in the issue, and the fix is already available in the main branch. The issue is caused by a subtle difference in how CommonJS modules are handled in Node ESM environments.

Recommendation

Apply the workaround by updating the botFrameworkJwtDepsPromise as shown in the local hot-fix, or upgrade to a version of openclaw and @openclaw/msteams that includes the commit `b3

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix msteams: v2026.4.26 ships broken JWT validator (jwt.verify is not a function); fix b3bc60ae missed the cut [1 comments, 2 participants]