You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bot Framework Python SDK的ActivityHandler中获取Teams用户访问令牌用于外部API调用

如何在Bot Framework Python SDK的ActivityHandler中获取Teams用户访问令牌用于外部API调用

嗨,我来帮你解决这个问题!结合你目前的场景,有两种靠谱的方案可以实现需求,我给你详细说说:

方案一:优化你当前的turn_state存储方式

你现在重写适配器方法把令牌存到turn_state的思路是完全可行的,而且是官方推荐的传递上下文数据的方式。不过可以简化一下实现,不用同时重写process_activity和process_activity_with_identity,只需要重写process_activity就够了:

class CustomBotFrameworkAdapter(BotFrameworkAdapter):
    async def process_activity(
        self,
        activity: Activity,
        auth_header: str,
        callback: Callable[[TurnContext], Awaitable[None]],
    ) -> Response:
        # 把授权令牌存入turn_state
        async def modified_callback(context: TurnContext):
            context.turn_state["AUTH_TOKEN"] = auth_header
            await callback(context)
        
        return await super().process_activity(activity, auth_header, modified_callback)

之后在你的ActivityHandler方法里,就可以直接从turn_state取出令牌:

class MyBot(ActivityHandler):
    async def on_message_activity(self, turn_context: TurnContext):
        auth_token = turn_context.turn_state.get("AUTH_TOKEN", "")
        if auth_token:
            # 这里用令牌调用外部API
            await turn_context.send_activity(f"成功获取到令牌:{auth_token[:10]}...")
        else:
            await turn_context.send_activity("未获取到用户授权令牌")

方案二:通过TurnContext直接获取身份信息(更规范的方式)

其实Teams发送的Authorization头里的令牌是Bot Framework的服务令牌,如果你要调用的外部API需要的是用户的Graph API令牌或者自定义令牌,更规范的做法是通过Bot Framework的身份验证系统来获取用户的有效令牌,而不是直接用请求头里的令牌。

具体步骤是:

  1. 确保你的Bot已经在Azure AD里注册了对应的API权限(比如User.Read之类的Graph权限)
  2. 在ActivityHandler里,通过turn_context.adapter调用get_user_token方法来获取用户令牌:
class MyBot(ActivityHandler):
    async def on_message_activity(self, turn_context: TurnContext):
        try:
            # 替换成你的Azure AD应用的连接名称(在Azure Bot服务中配置)
            token_response = await turn_context.adapter.get_user_token(
                turn_context,
                connection_name="你的连接名称",
                magic_code=""  # 如果是首次授权,留空即可,Bot会自动引导用户完成授权流程
            )
            if token_response and token_response.token:
                user_access_token = token_response.token
                # 用这个令牌调用外部API
                await turn_context.send_activity(f"成功获取用户访问令牌:{user_access_token[:10]}...")
            else:
                # 如果没有令牌,生成授权链接引导用户完成授权
                sign_in_link = await turn_context.adapter.get_sign_in_link(turn_context, "你的连接名称")
                await turn_context.send_activity(f"请点击下方链接完成授权:{sign_in_link}")
        except Exception as e:
            await turn_context.send_activity(f"获取令牌失败:{str(e)}")

这种方式的好处是,你拿到的是专门用于调用外部API的用户令牌,而不是Bot Framework的服务令牌,安全性和合规性更高,尤其是当你需要调用Microsoft Graph这类官方API时,这是标准做法。

总结

  • 如果你只是需要直接获取Teams发送的请求头里的令牌,方案一简单直接,完全匹配你的当前场景;
  • 如果你需要的是用户的有效访问令牌来调用第三方或Graph API,方案二更规范,也是官方推荐的实现方式。

备注:内容来源于stack exchange,提问作者Madhavareddy Vippala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:18:05