GCC High政府云Azure Bot用户认证报Unauthorized错误
问题基础信息
- 相同Bot配置在商用Azure环境可正常运行,仅在GCC High(美国政府高等级云)Azure环境部署时,Teams、Web Chat双渠道触发OAuth登录流程时抛出
Unauthorized异常,偶发BadGateway错误,已按官方部署文档完成基础配置仍无法解决。
已完成配置项
Azure门户(portal.azure.us)侧配置
- 创建Azure Bot资源
- 为Bot关联的Azure应用新增客户端密钥
- 认证设置中添加重定向URI:
https://tokengcch.botframework.azure.us/.auth/web/redirect - 完成消息终结点(Messaging endpoint)配置,创建OAuth连接设置且门户内测试连接可正常通过
代码侧基础配置
- 基于官方TeamsAuth示例代码改造,更新
AppSettings.json中MicrosoftAppId、MicrosoftAppPassword、ConnectionName参数 - 已在
startup.cs中测试过添加/移除如下GCCH环境服务地址信任代码,问题均存在:
string uri = "https://apiGCCH.botframework.azure.us"; MicrosoftAppCredentials.TrustServiceUrl(uri); AuthClientConfig.OAuthEndpoint = uri;
- 使用Bot Framework SDK 4.16版本
- 已在
startup.cs注入认证服务:services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>(); - 已添加全量GCCH环境配置项:
{ "MicrosoftAppId": "db9c0376-41c2-4abc-bee6-a1c2f64b4f61", "MicrosoftAppPassword": "ad8...", "ConnectionName": "ccsGraphAuth", "ChannelService": "https://botframework.azure.us", "OAuthUrl": "https://tokengcch.botframework.azure.us/", "ToChannelFromBotLoginUrl": "https://login.microsoftonline.us/MicrosoftServices.onmicrosoft.us", "ToChannelFromBotOAuthScope": "https://api.botframework.us", "ToBotFromChannelTokenIssuer": "https://api.botframework.us", "ToBotFromChannelOpenIdMetadataUrl": "https://login.botframework.azure.us/v1/.well-known/openidconfiguration", "ToBotFromEmulatorOpenIdMetadataUrl": "https://login.microsoftonline.us/cab8a31a-1906-4287-a0d8-4eef66b95f6e/v2.0/.well-known/openid-configuration", "ValidateAuthority": true }
现存报错信息
- 偶发BadGateway错误:
Microsoft.Bot.Schema.ErrorResponseException: Operation returned an invalid status code 'BadGateway' at Microsoft.Bot.Connector.Conversations.ReplyToActivityWithHttpMessagesAsync
- 稳定复现的Unauthorized错误,堆栈指向登录资源获取接口调用失败:
Exception Message: Microsoft.Rest.HttpOperationException: Operation returned an invalid status code 'Unauthorized' at Microsoft.Bot.Connector.OAuthClient.GetSignInResourceWithHttpMessagesAsync(String state, String codeChallenge, String emulatorUrl, String finalRedirect, Dictionary2 customHeaders, CancellationToken cancellationToken) at Microsoft.Bot.Connector.BotSignInExtensions.GetSignInResourceAsync(OAuthClient operations, String state, String codeChallenge, String emulatorUrl, String finalRedirect, CancellationToken cancellationToken) at Microsoft.Bot.Connector.Authentication.UserTokenClientImpl.GetSignInResourceAsync(String connectionName, Activity activity, String finalRedirect, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.UserTokenAccess.GetSignInResourceAsync(ITurnContext turnContext, OAuthPromptSettings settings, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.OAuthPrompt.SendOAuthCardAsync(OAuthPromptSettings settings, ITurnContext turnContext, IMessageActivity prompt, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.OAuthPrompt.BeginDialogAsync(DialogContext dc, Object options, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.DialogContext.BeginDialogAsync(String dialogId, Object options, CancellationToken cancellationToken) at Microsoft.BotBuilderSamples.MainDialog.PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) in D:\Bot\46.teams-auth\Dialogs\MainDialog.cs:line 51 at Microsoft.Bot.Builder.Dialogs.WaterfallDialog.OnStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.WaterfallDialog.RunStepAsync(DialogContext dc, Int32 index, DialogReason reason, Object result, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.WaterfallDialog.BeginDialogAsync(DialogContext dc, Object options, CancellationToken cancellationToken) at Microsoft.Bot.Builder.Dialogs.DialogContext.BeginDialogAsync(String dialogId, Object options, CancellationToken cancellationToken)
排查路径与修复方案
按优先级从高到低依次排查修复:
1. 移除硬编码的错误服务地址
代码中手动设置的OAuth端点存在两处错误:一是地址拼写错误,正确GCCH环境OAuth API地址为全小写带分段点的https://api.gcch.botframework.azure.us,现有配置缺少域名分隔点、大小写错误,会导致请求发往无效节点触发BadGateway;二是手动硬编码地址优先级高于配置文件读取,会覆盖正确配置参数。
修复操作:直接删除startup.cs中手动设置AuthClientConfig.OAuthEndpoint、TrustServiceUrl的代码块,ConfigurationBotFrameworkAuthentication会自动读取配置文件中的GCCH环境参数,无需手动指定。
2. 修正OAuthUrl配置的尾斜杠问题
现有配置中OAuthUrl参数末尾多余的斜杠会导致SDK拼接请求路径时出现//api/signin格式的异常路径,GCCH环境网关不会自动归一化该类路径,会直接返回401错误。
修复操作:将配置项修改为"OAuthUrl": "https://tokengcch.botframework.azure.us",移除末尾斜杠。
3. 校验Azure AD应用注册配置
登录Azure Government门户的应用注册页面,找到Bot关联的应用检查以下配置:
- 「支持的账户类型」必须选择为任何组织目录中的账户和个人Microsoft账户,单租户/仅组织内账户配置会导致Bot框架服务调用令牌接口时被AAD拒绝,返回401。
- 「认证」页面下,除已配置的重定向URI外,需要在隐式流和混合流选项中勾选
ID令牌和访问令牌,GCC High环境的Bot OAuth流程不支持纯PKCE无隐式流配置。 - 「API权限」页面下,必须添加
https://api.botframework.us/.default权限,且手动点击「授予管理员同意」,该权限在商用环境会自动同意,但GCC High环境需要手动操作。
4. 修复SDK版本兼容bug
Bot Framework SDK 4.16版本存在GCCH环境适配bug:读取ChannelService配置时不会自动切换UserTokenClient的认证受众,默认使用商用环境的https://api.botframework.com作为令牌请求受众,拿到的令牌无法通过GCCH节点校验。
修复操作:优先升级SDK到4.18及以上稳定版本,该bug在4.17.2补丁版本中已修复;如果暂时无法升级,可在startup.cs中添加如下代码手动指定Token客户端参数:
services.AddSingleton<IUserTokenClient>(sp => { var config = sp.GetRequiredService<IConfiguration>(); var credentials = new MicrosoftAppCredentials( config["MicrosoftAppId"], config["MicrosoftAppPassword"], config["ToChannelFromBotOAuthScope"], config["ToChannelFromBotLoginUrl"] ); return new UserTokenClient( new Uri(config["OAuthUrl"]), credentials, null, sp.GetRequiredService<ILoggerFactory>().CreateLogger<UserTokenClient>() ); });
5. 校验网络访问策略
如果Bot部署在GCC High环境内部VNET中,需要确认出站策略放通以下地址的443端口访问,且不要走商用环境代理转发:
*.botframework.azure.uslogin.microsoftonline.uslogin.botframework.azure.us
代理转发时如果修改了请求的Authorization头,也会触发401错误。
验证说明
完成配置修改后重启Bot服务,先在Web Chat渠道测试触发登录,确认可正常弹出OAuth登录卡片无报错;Teams渠道测试需要等待15-30分钟,GCC High环境的租户配置同步存在延迟,修改后立即测试会命中旧配置缓存。
内容的提问来源于stack exchange,提问作者Vivek

