Teams Bot中OAuthPrompt对部分企业成员无法返回TokenResponse问题排查
Teams Bot OAuthPrompt 登出后部分用户认证异常的问题排查与修复
核心问题根源
- 登出操作未清理对话状态,导致用户后续消息仍进入旧的认证对话框流程
- 内存缓存的用户请求内容未在登出时清除,引发逻辑判断异常
- OAuthPrompt配置与对话状态的协同处理存在疏漏
具体修复方案
1. 登出时同步清理对话状态与缓存
原登出逻辑仅执行了用户登出,未重置对话状态和用户缓存,导致后续消息仍走旧的对话框流程。修改OnMessageActivityAsync中的登出分支:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) { var userTokenClient = turnContext.TurnState.Get<UserTokenClient>(); if (turnContext.Activity.Text.Equals("logout")) { await userTokenClient.SignOutUserAsync(turnContext.Activity.From.Id, _connectionName, turnContext.Activity.ChannelId, cancellationToken: cancellationToken); // 清除对话状态,重置对话框流程 var dialogState = _conversationState.CreateProperty<DialogState>(nameof(DialogState)); await dialogState.SetAsync(turnContext, new DialogState(), cancellationToken); await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); // 清除用户内存缓存的请求内容 _memoryCache.Remove(turnContext.Activity.From.Id); await turnContext.SendActivityAsync(MessageFactory.Text("You have been signed out."), cancellationToken); return; } // 原有逻辑... }
2. 优化对话框Token验证逻辑
在LoginStepAsync中,当OAuthPrompt返回null时,主动尝试重新获取Token(适配SSO自动登录场景),同时处理缓存不存在的情况避免循环:
private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var tokenResponse = (TokenResponse)stepContext.Result; var userTokenClient = stepContext.Context.TurnState.Get<UserTokenClient>(); // 如果Prompt返回null,主动尝试获取Token(处理SSO自动完成的情况) if (tokenResponse == null) { tokenResponse = await userTokenClient.GetUserTokenAsync( stepContext.Context.Activity.From.Id, _configuration["ConnectionName"], stepContext.Context.Activity.ChannelId, null, cancellationToken); } String? question; _memoryCache.TryGetValue(stepContext.Context.Activity.From.Id, out question); if (tokenResponse?.Token != null && question != null) { await _teamsService.ProcessTeamsMessageAsync(stepContext.Context, question, tokenResponse.Token, cancellationToken); // 处理完成后清除缓存 _memoryCache.Remove(stepContext.Context.Activity.From.Id); } else { await stepContext.Context.SendActivityAsync(MessageFactory.Text("Stuur je vraag nogmaals aub."), cancellationToken); // 若缓存不存在,直接结束对话框,让用户重新触发流程 if (question == null) { return await stepContext.EndDialogAsync(cancellationToken: cancellationToken); } return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken); } return await stepContext.EndDialogAsync(cancellationToken: cancellationToken); }
3. 调整OAuthPrompt配置
将EndOnInvalidMessage设为false,避免用户在认证过程中发送消息导致Prompt异常终止,确保SSO流程正常完成:
AddDialog(new OAuthPrompt( nameof(OAuthPrompt), new OAuthPromptSettings { ConnectionName = configuration["ConnectionName"] ?? throw new ArgumentException("ConnectionName"), Text = "Please Sign In", Title = "Sign In", Timeout = 300000, EndOnInvalidMessage = false // 修改为false }));
4. 确保对话状态持久化
检查服务配置与适配器,确保ConversationState正确注册并使用:
- 服务注册添加:
services.AddSingleton<ConversationState>();
- 适配器中添加对话状态中间件:
public AdapterWithErrorHandler(BotFrameworkAuthentication auth, ConversationState conversationState, ILogger<BotFrameworkHttpAdapter> logger) : base(auth, logger) { Use(new TeamsSSOTokenExchangeMiddleware()); // 注册对话状态中间件 Use(new ConversationStateMiddleware(conversationState)); // 原有错误处理逻辑... }
内容的提问来源于stack exchange,提问作者Jasper B
相关产品推荐
相关产品推荐

