Microsoft Teams平台Azure Bot添加SSO功能及落地实现问题咨询
已完成的Azure Bot启用SSO前置配置
- 创建Bot
- 在Channels中添加Microsoft Teams
- 在配置页添加消息端点,示例为
https://myproxy.proxyapp.com/teams/app/activity - 为Microsoft应用ID生成client secret
- 在Microsoft应用身份验证配置的Web平台下添加重定向URI:
https://token.botframework.com/.auth/web/redirect - 在Microsoft应用的API权限中添加
email offline_access openid profile,默认已包含User.Read权限 - 在「公开API」配置中添加
api://botid-{Microsoft app id},新增access_as_user作用域,同时添加Web端(1fec8e78-bce4-4aaf-ab1b-5451cc387264)和桌面端(5e3ce6c0-2b1f-4285-8d4b-75ee78787346)客户端应用 - 将Microsoft应用清单中的
accessTokenAcceptedVersion参数更新为2 - 为Bot添加OAuth连接,配置截图见

- 在Microsoft Teams中创建应用,将前述Microsoft应用ID关联为Bot ID,Teams应用清单完整内容见下文
附相关配置文件
消息端点收到的用户Hi消息结构体
{ "text": "hi", "textFormat": "plain", "attachments": [ { "contentType": "text/html", "content": "<div>hi</div>" } ], "type": "message", "timestamp": "2021-10-05T18:27:21.5454867Z", "localTimestamp": "2021-10-05T23:57:21.5454867+05:30", "id": "1633458441515", "channelId": "msteams", "serviceUrl": "https://smba.trafficmanager.net/in/", "from": { "id": "29:1kR5UGDG5iTFhsVadKAadeYuzsLEhMYK_YFxb7_Y62nAilJVLIMiPtC8oLrGGyK7wZTaFc8-jlVxJq3q0bpoBMw", "name": "Ashish Sood", "aadObjectId": "3836************************be046" }, "conversation": { "conversationType": "personal", "tenantId": "1734*************************bb8ecf", "id": "a:1xMOdsbv02hfl2J4GUGA7-WemaLGCOxFlzsSNcQ9StjIMAAKn64tJ0zxKk25b02NMTl3rc7nbNffMZGXVYfraNIDKnptC01oeLRv7Ngh2WMCyOrmBT2KaDleQXSU2s4MY" }, "recipient": { "id": "28:18c9**********************02b9", "name": "NOW_Virtual_Agent_SSO_Bot" }, "entities": [ { "locale": "en-GB", "country": "GB", "platform": "Mac", "timezone": "Asia/Calcutta", "type": "clientInfo" } ], "channelData": { "tenant": { "id": "1734************************b8ecf" } }, "locale": "en-GB", "localTimezone": "Asia/Calcutta" }
Teams应用manifest.json内容
{ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.11/MicrosoftTeams.schema.json", "manifestVersion": "1.11", "version": "1.0.0", "id": "9a83***************************177d", "packageName": "com.microsoft.teams.devapp", "developer": { "name": "SSO Bot App", "websiteUrl": "https://www.teams.com", "privacyUrl": "https://www.teams.com/privacy", "termsOfUseUrl": "https://www.teams.com/termsofuse" }, "icons": { "color": "color.png", "outline": "outline.png" }, "name": { "short": "SSO Bot App", "full": "SSO Bot App" }, "description": { "short": "SSO Bot App", "full": "SSO Bot App" }, "accentColor": "#FFFFFF", "staticTabs": [ { "entityId": "conversations", "scopes": [ "personal" ] }, { "entityId": "about", "scopes": [ "personal" ] } ], "bots": [ { "botId": "18c9**********************02b9", "scopes": [ "personal" ], "supportsFiles": true, "isNotificationOnly": false } ], "permissions": [ "identity", "messageTeamMembers" ], "validDomains": [ "token.botframework.com" ], "webApplicationInfo": { "id": "18c9**********************02b9", "resource": "api://botid-18c9**********************02b9" } }
问题解答
问题1:如何实现Bot发送携带包含tokenExchangeResource属性的OAuthCard的消息
- 先确认你在Azure Bot配置的OAuth连接名称,后续构造卡片要用到这个名称
- 用Bot Framework SDK构造OAuthCard,核心参数配置如下:
connectionName:填你刚才确认的OAuth连接名tokenExchangeResource:填入你之前配置的公开API URI,也就是api://botid-<你的Microsoft应用ID>,如果需要指定作用域可以加上/access_as_user后缀
- 把构造好的OAuthCard作为附件添加到返回的Activity消息中,调用SDK的回复接口把消息发回给Teams客户端即可
附Node.js SDK示例代码:
const { OAuthCard, CardFactory, MessageFactory } = require('botbuilder'); const oauthCard = CardFactory.oauthCard( '你的OAuth连接名', '登录', '请点击登录完成身份验证', null, { id: '<你的Microsoft应用ID>', uri: 'api://botid-<你的Microsoft应用ID>/access_as_user' } ); const reply = MessageFactory.attachment(oauthCard); await turnContext.sendActivity(reply);
问题2:如何使用收到的Hi消息结构体完成6步SSO认证流程
你收到的是用户触发的初始消息,后续按以下步骤执行即可:
- 拿到当前消息的上下文后,按上述问题1的方法构造并返回带tokenExchangeResource的OAuthCard,这是SSO流程的触发起点
- Teams客户端收到OAuthCard后,会自动识别tokenExchangeResource配置,无需用户操作,直接向AAD请求当前登录用户的SSO令牌
- Teams客户端拿到令牌后,会向你的消息端点发送类型为
signin/tokenExchange的invoke请求,请求体中会携带用户的SSO令牌 - 你收到tokenExchange请求后,首先校验令牌合法性:校验令牌的签发方是AAD、受众是你的Microsoft应用ID、令牌中携带的用户aadObjectId和初始Hi消息中
from.aadObjectId字段一致,避免伪造请求 - 校验通过后,使用该令牌、你的Microsoft应用ID、client secret,向Bot Service OAuth服务发起令牌交换请求,获取你实际需要的下游API访问令牌(比如Graph API的访问令牌)
- 令牌交换成功后,即可用获取到的访问令牌调用对应的业务接口,向用户返回业务响应;如果交换失败(比如用户首次使用需要权限同意),则自动回退到常规的弹窗登录流程即可
内容的提问来源于stack exchange,提问作者Ashish Sood
相关产品推荐
相关产品推荐

