如何在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的身份验证系统来获取用户的有效令牌,而不是直接用请求头里的令牌。
具体步骤是:
- 确保你的Bot已经在Azure AD里注册了对应的API权限(比如
User.Read之类的Graph权限) - 在
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
相关产品推荐
相关产品推荐

