我正在尝试使用Microsoft botframework和打字稿中的SDK创建聊天机器人。我正在尝试让机器人对用户进行身份验证,然后代表他们与Azure DevOps进行交互。但是,虽然我能够在Azure门户中成功测试身份验证,但是当我尝试对Teams中的用户进行身份验证时,登录“成功”,但是该僵尸程序尝试访问Azure DevOps API时返回了401错误。
我是很多Microsoft堆栈的新手,并且在这里遵循指南:https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-authentication?view=azure-bot-service-4.0&tabs=javascript%2Cbot-oauth。
首先,我创建了我的Bot频道注册。它具有与之关联的应用程序注册(已手动创建)。在Azure Portal上的App Service中将appId和secret设置为环境变量。
第二,我为Azure Devops授权创建了另一个应用程序注册。此应用程序注册的重定向URI为“ https://token.botframework.com/.auth/web/redirect”,并为其创建了一个秘密。此应用程序注册也已设置为具有Azure Devops的API权限“ user_impersonation”。
第三,我进入了Bot频道注册,单击“设置”刀片,并配置了OAuth连接设置。此设置的名称为“ azureDevopsOauth”,是为Azure Active Directory V2服务提供商设置的,包括我在第二步中进行的应用程序注册的客户端ID,机密和租户ID。它还将范围设置为“ openid”。
当我单击此oauth配置顶部的“测试连接”时,一切正常。我被带到成功页面,并且能够在其中查看令牌。
继续讲代码,我知道团队对于OAuth有点时髦。我的应用程序是使用节点用Typescript编写的,并且需要重新调整以处理服务器方面。我的bot代码扩展了ActivityHandler,具有通常的onMember Leicester,onMessage和onDialog函数。我还添加了onTokenResponseEvent和onUnrecognizedActvityType来处理令牌响应和调用活动类型。
this.onTokenResponseEvent(async (context, next) => {
console.log('Running dialog with Token Response Event Activity.');
await this.dialog.run(context, this.dialogState);
await next();
});
this.onUnrecognizedActivityType(async (context, next) => {
if (context.activity.type === ActivityTypes.Invoke) {
await this.dialog.run(context, this.dialogState);
}
await next();
});
最后,在主对话框中,我创建了一个oauth提示符(连接名称也在App Service的环境变量中):
this.addDialog(new OAuthPrompt(OAUTH_PROMPT, {
connectionName: process.env.connectionName,
text: 'Before we get started, could you please sign in?',
title: 'Sign In',
timeout: 300000
}));
此提示将添加到此处的瀑布对话框:
this.addDialog(new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
this.loginStep.bind(this),
this.confirmStep.bind(this),
this.projectStep.bind(this),
this.serviceStep.bind(this),
this.getServiceDialogStep.bind(this)
]));
这是我的机器人的开始。因此,当您与其互动时,它将立即要求您登录。登录后,我可以看到流程转到了确认步骤,因为我正在那里注销令牌以进行调试。
我正在使用Azure Devops Node API来访问Azure API。我根据令牌响应使用承载令牌身份验证句柄进行了设置:
const authHandler = azdev.getBearerHandler(authToken);
this.connection = new azdev.WebApi(orgUrl, authHandler);
不幸的是,一旦代码移至项目步骤(试图获取连接和项目),我将收到401错误。该错误是在获取连接时引发的,因此它永远不会到达getProjects函数:
this.coreApi = await this.connection.getCoreApi();
let projects = await this.coreApi.getProjects();
我不知道可能是什么设置错误,但是理想情况下,我希望能够使用登录的用户凭据来访问这些服务。
如果有帮助,我得到的实际401错误对象是:
{
Error: TF400813: The user '' is not authorized to access this resource.
at RestClient.<anonymous> (/home/site/wwwroot/node_modules/typed-rest-client/RestClient.js:200:31)
at Generator.next (<anonymous>)
at fulfilled (/home/site/wwwroot/node_modules/typed-rest-client/RestClient.js:6:58)
at process._tickCallback (internal/process/next_tick.js:68:7)
statusCode: 401,
result: {
'$id': '1',
innerException: null,
message: 'TF400813: The user \'\' is not authorized to access this resource.',
typeName: 'Microsoft.TeamFoundation.Framework.Server.UnauthorizedRequestException, Microsoft.TeamFoundation.Framework.Server',
typeKey: 'UnauthorizedRequestException',
errorCode: 0,
eventId: 3000
}
}
这几乎是我问题的详尽描述。如果有人可以帮助我,我将非常感激!我希望我提供了足够的详细信息,但是如果我可以提供更多信息,请告诉我。
答案 0 :(得分:1)
我对Azure Devops api不太了解,但是可能您使用的令牌不正确。
在“ OAuth连接设置”中,将范围设置为“ openid”,因此您获得了以Graph api(而不是Azure Devops rest api)作为受众的令牌。
您可以通过将令牌放在jwt.ms上,检查已解码的aud
和scp
声明来进行验证。它应该与Azure Devops无关。
OAuth2令牌仅可用于其预期的资源(受众)。您不能使用图令牌与Azure开发运营API进行对话。
请尝试使用正确的Azure devops范围更新“ azureDevopsOauth” OAuth连接设置。可用范围似乎已记录在here中,例如如果您想阅读构建工件,请使用vso.build
而不是openid
。您可以将多个用逗号分隔的azure dev ops范围作为值:
vso.build,vso.code,vso.release
并且请选择启用方案所需的最小范围。
执行完此操作后,OAuthPrompt应该会抛出用户同意屏幕-在您同意之前,还要仔细检查那里的信息。
答案 1 :(得分:0)
我认为这与团队以不同方式处理活动的方式有关。这是来自Node sample的更多信息:
在此阶段,此样本的主要重点是如何使用Bot 机器人中对oauth的框架支持。优先排序的原因 这是因为团队的行为与其他渠道中的行为略有不同 对此。具体来说,调用活动会发送到机器人,而不是 而不是其他渠道使用的“事件活动”。此调用活动 如果正在使用OAuthPrompt,则必须转发到对话框。这个 通过将ActivityHandler子类化来完成,此示例包括一个 可重用的TeamsActivityHandler。这个班是未来的候选人 包含在Bot Framework SDK中。
我的建议是快速测试此Node示例,以查看是否可以在Teams中使用它。然后,您应该能够从Node示例中获取该方法,并将其应用于TypeScript(目前 目前还没有TypeScript示例)。