如何在Bot Framework中使用TeamsBotSsoPrompt获取SSO令牌?
Teams机器人SSO令牌获取问题排查与修复
核心问题分析
你的代码存在三个关键问题导致无法进入瀑布流第二步:
- 每次消息都新建对话框实例:在
OnMessageActivityAsync中每次创建WaterfallDialog和TeamsBotSsoPrompt,导致对话状态无法关联,验证完成后找不到对应的对话框上下文。 OnTeamsSigninVerifyStateAsync未处理对话续流:仅打印日志,未触发对话继续,无法将验证结果传递回瀑布流。- 未持久化对话状态:每次回合结束后未保存
ConversationState,导致对话状态丢失。
修复步骤与代码示例
1. 重构对话框初始化逻辑
将对话框注册到DialogSet中,避免每次消息重复创建,确保对话上下文一致性。
2. 完善OnTeamsSigninVerifyStateAsync方法
在该方法中继续对话流程,让验证结果能传递到瀑布流第二步。
3. 确保对话状态持久化
在OnTurnAsync末尾保存ConversationState。
修改后的完整代码:
using Microsoft.Bot.Builder; using Microsoft.Bot.Builder.Teams; using Microsoft.Bot.Schema; using Microsoft.Bot.Builder.Dialogs; using DataPlatformBot.SSO; using Microsoft.TeamsFx.Bot; using Microsoft.Extensions.Options; using Microsoft.TeamsFx.Configuration; namespace DataPlatformBot; public class TeamsBot : TeamsActivityHandler { readonly ILogger<TeamsBot> _logger; readonly SsoDialog _ssoDialog; readonly IStatePropertyAccessor<DialogState> _dialogState; readonly BotAuthenticationOptions _botAuthOptions; readonly BotState _conversationState; readonly DialogSet _dialogSet; public TeamsBot(ConversationState conversationState, IOptions<BotAuthenticationOptions> botAuthOptions, SsoDialog ssoDialog, ILogger<TeamsBot> logger) { _ssoDialog = ssoDialog; _logger = logger; _conversationState = conversationState; _dialogState = _conversationState.CreateProperty<DialogState>("DialogState"); _botAuthOptions = botAuthOptions.Value; // 初始化DialogSet并注册对话框 _dialogSet = new DialogSet(_dialogState); var ssoSettings = new TeamsBotSsoPromptSettings(_botAuthOptions, new string[] { "User.Read" }); _dialogSet.Add(new TeamsBotSsoPrompt(nameof(TeamsBotSsoPrompt), ssoSettings)); _dialogSet.Add(new WaterfallDialog("SsoWaterfall", new List<WaterfallStep> { async (stepContext, cancellationToken) => { return await stepContext.BeginDialogAsync(nameof(TeamsBotSsoPrompt), null, cancellationToken); }, async (stepContext, cancellationToken) => { var tokenResponse = (TeamsBotSsoPromptTokenResponse)stepContext.Result; _logger.LogInformation($"获取到SSO令牌: {tokenResponse.Token}"); return await stepContext.EndDialogAsync(); } })); } protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) { var dialogContext = await _dialogSet.CreateContextAsync(turnContext, cancellationToken); var results = await dialogContext.ContinueDialogAsync(cancellationToken); if (results.Status == DialogTurnStatus.Empty) { await dialogContext.BeginDialogAsync("SsoWaterfall", null, cancellationToken); } } protected override async Task OnTeamsSigninVerifyStateAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken) { _logger.LogInformation("Receive invoke activity of teams sign in verify state"); // 继续对话流程,传递验证结果 var dialogContext = await _dialogSet.CreateContextAsync(turnContext, cancellationToken); await dialogContext.ContinueDialogAsync(cancellationToken); } public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken)) { await base.OnTurnAsync(turnContext, cancellationToken); // 保存对话状态 await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); } }
额外验证点
- 确认Azure AD应用注册的重定向URI已正确配置为
https://token.botframework.com/.auth/web/redirect - 确保机器人的权限范围(如
User.Read)已在Azure AD中正确配置并获得管理员同意(如果需要) - 验证Teams客户端的SSO设置未被禁用
内容的提问来源于stack exchange,提问作者Krumelur
相关产品推荐
相关产品推荐

