-
-
Notifications
You must be signed in to change notification settings - Fork 69.5k
[msteams] Inline image downloads fail in 1:1 chats — inbound media uses bot adapter token instead of MSAL Graph token #28014
Description
Environment
- OpenClaw: 2026.2.25 (latest)
- OS: Ubuntu 22.04 (x64), Node v24.13.1
- Azure Bot: Single-tenant, MS Teams channel enabled
- Permission:
Chat.Read.All(Application) granted with admin consent
Problem
When a user sends an inline image (paste/screenshot) in a 1:1 Teams chat with the bot, the msteams plugin detects the image but fails to download it.
Logs show:
"html attachment summary"
"graph media fetch empty"
"inline images detected but none downloaded"
Root Cause
resolveMSTeamsInboundMedia() in src/monitor-handler/inbound-media.ts passes the Bot Framework turn context tokenProvider to downloadMSTeamsGraphMedia(). This provider calls getAccessToken("https://graph.microsoft.com") but returns a Bot Connector-scoped token, not a Graph API token with Chat.Read.All scope.
Meanwhile, resolveGraphToken() in src/graph.ts correctly uses MsalTokenProvider with the bot's appId/appPassword to get a properly-scoped Graph token via client credentials flow. This code path is not used by the inbound media handler.
Verified: Manual curl test using the same appId/appPassword with client credentials grant to https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token returns a valid Graph token. The credentials and permissions are correct — the issue is which token provider is used.
Suggested Fix
Have downloadMSTeamsGraphMedia() fall back to resolveGraphToken() (MSAL client credentials) when the bot adapter's tokenProvider.getAccessToken("https://graph.microsoft.com") fails or returns a token without Graph scopes.
The MSAL token acquisition code already exists in the same plugin (graph.ts:52-67) — it just needs to be wired into the inbound media path.
Workaround
File attachments (drag-and-drop) may use a different download path. Inline paste/screenshots in 1:1 chats are broken.