Skip to content

[msteams] Inline image downloads fail in 1:1 chats — inbound media uses bot adapter token instead of MSAL Graph token #28014

@Tranman324

Description

@Tranman324

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions