您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

使用 Bot Connector API 进行身份验证

机器人使用通过安全通道 (SSL/TLS) 的 HTTP 与 Bot Connector 服务进行通信。 当机器人向 Connector 服务发送请求时,它必须包含 Connector 服务可以用来验证其身份的信息。 同样,当 Connector 服务向机器人发送请求时,它必须包含机器人可以用来验证其身份的信息。 本文介绍在机器人和 Bot Connector 服务之间进行的服务级身份验证的身份验证技术和要求。 如果正在编写自己的身份验证代码,必须实现本文所述的安全过程,以便机器人能够与 Bot Connector 服务交换消息。

重要

如果正在编写自己的身份验证代码,则必须正确实现所有安全程序。 通过实现本文中的所有步骤,可以降低攻击者能够读取发送到机器人的消息、发送模拟机器人的消息以及窃取密钥的风险。

如果使用的是 Bot Framework SDK for .NETBot Framework SDK for Node.js,则不需要实现本文所述的安全程序,因为 SDK 会自动为你完成。 只需使用在注册期间为机器人获得的应用 ID 和密码配置项目,SDK 将处理其余部分。

身份验证技术

四个身份验证技术用于在机器人和 Bot Connector 之间建立信任:

技术 说明
SSL/TLS SSL/TLS 适用于所有服务到服务连接。 X.509v3 证书用于建立所有 HTTPS 服务的标识。 客户端应始终检查服务证书以确保它们受信任且有效。 (客户端证书不作为此方案的一部分使用。)
OAuth 2.0 OAuth 2.0 使用 Azure Active Directory (Azure AD) v2 帐户登录服务来生成机器人可用于发送消息的安全令牌。 此令牌是服务到服务令牌;无需用户登录。
JSON Web 令牌 (JWT) JSON Web 令牌用于编码向机器人发送和从中发出的令牌。 客户端应根据本文中所述的要求完全验证他们收到的所有 JWT 令牌 。
OpenID 元数据 Bot Connector 服务发布一个有效令牌列表,用于在已知静态终结点上将自己的 JWT 令牌签署到 OpenID 元数据。

本文介绍如何通过标准 HTTPS 和 JSON 使用这些技术。 不需要特殊 SDK,尽管你可能发现 OpenID 之类的帮助程序很有用。

对从机器人到 Bot Connector 服务的请求进行身份验证

若要与 Bot Connector 服务通信,必须使用以下格式在每个 API 请求的 Authorization 标头中指定访问令牌:

Authorization: Bearer ACCESS_TOKEN

此图显示 bot-to-connector 身份验证的步骤:

依次对 MSA 登录服务和机器人进行身份验证

步骤 1:从 Azure AD v2 帐户登录服务请求访问令牌

重要

如果尚未这样做,则必须向 Bot Framework 注册机器人以获取其应用 ID 和密码。 若要请求访问令牌,需要机器人的应用 ID 和密码。

若要从登录服务请求访问令牌,请发出以下请求,将 MICROSOFT-APP-ID 和 MICROSOFT-APP-PASSWORD 替换为向 Bot Framework 注册机器人时获得的机器人应用 ID 和密码。

POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=MICROSOFT-APP-ID&client_secret=MICROSOFT-APP-PASSWORD&scope=https%3A%2F%2Fapi.botframework.com%2F.default

步骤 2:从 Azure AD v2 帐户登录服务响应获取 JWT 令牌

如果应用程序已由登录服务授权,那么 JSON 响应正文将指定访问令牌、其类型及其过期时间(以秒为单位)。

将令牌添加到请求的 Authorization 标头时,必须使用此响应中指定的确切值(即,不转义或编码令牌值)。 访问令牌有效,直到过期。 为了防止令牌过期影响机器人性能,可以选择缓存并主动刷新令牌。

此示例显示来自 Azure AD v2 帐户登录服务的响应:

HTTP/1.1 200 OK
... (other headers)
{
    "token_type":"Bearer",
    "expires_in":3600,
    "ext_expires_in":3600,
    "access_token":"eyJhbGciOiJIUzI1Ni..."
}

步骤 3:指定请求的 Authorization 标头中的 JWT 令牌

当向 Bot Connector 服务发送 API 请求,使用此格式指定请求的 Authorization 标头中的访问令牌:

Authorization: Bearer ACCESS_TOKEN

发送到 Bot Connector 服务的所有请求都必须在 Authorization 标头中包含访问令牌。 如果令牌格式正确、令牌未过期且令牌由 Azure AD v2 帐户登录服务生成,则 Bot Connector 服务将对请求授权。 需执行额外检查以确保令牌属于发送请求的机器人。

下面的示例演示如何指定请求 Authorization 标头中的访问令牌。

POST https://smba.trafficmanager.net/apis/v3/conversations/12345/activities
Authorization: Bearer eyJhbGciOiJIUzI1Ni...

(JSON-serialized Activity message goes here)

重要

只在发送到 Bot Connector 服务的请求的 Authorization 标头中指定 JWT 令牌。 不要将令牌发送到非安全通道,也不要将其包含在发送给其他服务的 HTTP 请求中。 从 Azure AD v2 帐户登录服务获取的 JWT 令牌类似于密码,应谨慎处理。 拥有令牌的任何人都可以使用它代表机器人执行操作。

机器人到 Connector:示例 JWT 组件

header:
{
  typ: "JWT",
  alg: "RS256",
  x5t: "<SIGNING KEY ID>",
  kid: "<SIGNING KEY ID>"
},
payload:
{
  aud: "https://api.botframework.com",
  iss: "https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/",
  nbf: 1481049243,
  exp: 1481053143,
  appid: "<YOUR MICROSOFT APP ID>",
  ... other fields follow
}

备注

在实践中,实际字段可能会有所不同。 创建并验证上面指定的所有 JWT 令牌。

对从 Bot Connector 服务到机器人的请求进行身份验证

当 Bot Connector 服务将请求发送到机器人时,它会在请求的 Authorization 标头中指定已签名的 JWT 令牌。 通过验证已签名的 JWT 令牌的真实性,机器人可以对来自 Bot Connector 服务的调用进行身份验证。

此图显示 connector-to-bot 身份验证的步骤:

对从 Bot Connector 到机器人的调用进行身份验证

步骤 2:获取 OpenID 元数据文档

OpenID 元数据文档指定第二个文档的位置,其中列出了 Bot Connector 服务的有效签名密钥。 若要获取 OpenID 元数据文档,请通过 HTTPS 发出此请求:

GET https://login.botframework.com/v1/.well-known/openidconfiguration

提示

这是静态 URL,可以硬编码到应用程序。

下面的示例演示响应 GET 请求返回的 OpenID 元数据文档。 jwks_uri 属性指定包含 Bot Connector 服务的有效签名密钥的文档的位置。

{
    "issuer": "https://api.botframework.com",
    "authorization_endpoint": "https://invalid.botframework.com",
    "jwks_uri": "https://login.botframework.com/v1/.well-known/keys",
    "id_token_signing_alg_values_supported": [
      "RS256"
    ],
    "token_endpoint_auth_methods_supported": [
      "private_key_jwt"
    ]
}

步骤 3:获取有效签名密钥的列表

若要获取有效的签名密钥列表,请通过 HTTPS 向 OpenID 元数据文档中的 jwks_uri 属性指定的 URL 发出 GET 请求。 例如:

GET https://login.botframework.com/v1/.well-known/keys

响应正文指定 JWK 格式的文档,还包括每个密钥的其他属性:endorsements

提示

密钥列表是稳定的,可以缓存,但随时可能会添加新密钥。 为了确保机器人在使用这些密钥之前具有文档最新副本,所有机器人实例应至少每 24 小时刷新一次文档的本地缓存。

每个密钥中的 endorsements 属性包含一个或多个字符串,可用于验证在传入请求的 Activity 对象的 channelId 属性中定义的通道 ID 是否可信。 需要认可的通道 ID 列表在每个机器人中都可配置。 默认情况下,它将是所有已发布通道 ID 的列表,尽管机器人开发人员可能会通过任何一种方式重写选定通道的 ID 值。

步骤 4:验证 JWT 令牌

若要验证由 Bot Connector 服务发送的令牌的真实性,必须从请求的 Authorization 标头中提取令牌、分析令牌、验证其内容并验证其签名。

JWT 分析库适用于许多平台,并且大多数对 JWT 令牌实现安全且可靠的分析,尽管通常情况下必须配置这些库以请求令牌的某些特征(其颁发者、受众等)包含正确的值。 分析令牌时,必须配置分析库或编写你自己的验证来确保令牌满足这些要求:

  1. 令牌在 HTTP Authorization 标头中使用“持有者”方案发送。
  2. 令牌是有效的 JSON,符合 JWT 标准
  3. 令牌包含值为 https://api.botframework.com 的“颁发者”声明。
  4. 该令牌包含一个“受众”声明,其值等于机器人的 Microsoft 应用 ID。
  5. 该令牌在其有效期内。 行业标准时钟偏差为 5 分钟。
  6. 令牌具有有效的加密签名,包含在步骤 3 中检索到的 OpenID 密钥文档中列出的密钥,使用的是步骤 2 中检索到的 Open ID 元数据文档的 id_token_signing_alg_values_supported 属性中指定的签名算法。
  7. 该令牌包含“serviceUrl”声明,其值与传入请求的 Activity 对象根的 serviceUrl 属性匹配。

如果需要认可通道 ID:

  • 应请求使用通道 ID 发送到机器人的任何 Activity 对象随附 JWT 令牌,并签署有对该通道的认可。
  • 如果不存在认可,则机器人应通过返回 HTTP 403(禁止) 状态代码拒绝该请求。

重要

所有这些要求都很重要,尤其是要求 4 和 6。 如果未能实现所有这些验证要求将使机器人受到攻击,这可能会导致机器人公开其 JWT 令牌。

实施者不应公开禁用发送给机器人的 JWT 令牌的验证的方法。

Connector 到机器人:示例 JWT 组件

header:
{
  typ: "JWT",
  alg: "RS256",
  x5t: "<SIGNING KEY ID>",
  kid: "<SIGNING KEY ID>"
},
payload:
{
  aud: "<YOU MICROSOFT APP ID>",
  iss: "https://api.botframework.com",
  nbf: 1481049243,
  exp: 1481053143,
  ... other fields follow
}

备注

在实践中,实际字段可能会有所不同。 创建并验证上面指定的所有 JWT 令牌。

对从 Bot Framework Emulator 到机器人的请求进行身份验证

Bot Framework Emulator 是一个桌面工具,可用于测试机器人的功能。 虽然 Bot Framework Emulator 使用如上所述的相同身份验证技术,但它无法模拟真实的 Bot Connector 服务。 相反,它使用将机器人连接到机器人时指定的 Microsoft 应用 ID Emulator Microsoft 应用密码来创建与机器人创建的令牌相同的令牌。 当Emulator向机器人发送请求时,它会在请求标头中指定 JWT 令牌,实质上是使用机器人自己的凭据对请求 Authorization 进行身份验证。

如果要实现身份验证库,并想要接受来自 Bot Framework Emulator 的请求,则必须添加此附加验证路径。 该路径在结构上类似于 Connector -> Bot 验证路径,但它使用 MSA 的 OpenID 文档而不是 Bot Connector 的 OpenID 文档。

此图显示了Emulator机器人身份验证的步骤:

对从 Bot Framework Emulator 到机器人的调用进行身份验证


步骤 2:获取 MSA OpenID 元数据文档

OpenID 元数据文档指定第二个文档的位置,其中列出了有效签名密钥。 若要获取 MSA OpenID 元数据文档,请通过 HTTPS 发出此请求:

GET https://login.microsoftonline.com/botframework.com/v2.0/.well-known/openid-configuration

下面的示例演示响应 GET 请求返回的 OpenID 元数据文档。 jwks_uri 属性指定文档的位置,其中包含有效的签名密钥。

{
    "authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
    "token_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/token",
    "token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt"],
    "jwks_uri":"https://login.microsoftonline.com/common/discovery/v2.0/keys",
    ...
}

步骤 3:获取有效签名密钥的列表

若要获取有效的签名密钥列表,请通过 HTTPS 向 OpenID 元数据文档中的 jwks_uri 属性指定的 URL 发出 GET 请求。 例如:

GET https://login.microsoftonline.com/common/discovery/v2.0/keys
Host: login.microsoftonline.com

响应正文指定 JWK 格式的文档。

步骤 4:验证 JWT 令牌

若要验证 Emulator 发送的令牌的真实性,必须从请求的 标头中提取令牌,分析令牌,验证其内容,并 Authorization 验证其签名。

JWT 分析库适用于许多平台,并且大多数对 JWT 令牌实现安全且可靠的分析,尽管通常情况下必须配置这些库以请求令牌的某些特征(其颁发者、受众等)包含正确的值。 分析令牌时,必须配置分析库或编写你自己的验证来确保令牌满足这些要求:

  1. 令牌在 HTTP Authorization 标头中使用“持有者”方案发送。
  2. 令牌是有效的 JSON,符合 JWT 标准
  3. 令牌包含一个"颁发者"声明,其中包含非政府 事例的突出显示 值之一。 检查这两个颁发者值可确保检查安全协议 v3.1 和 v3.2 颁发者值。
  4. 该令牌包含一个“受众”声明,其值等于机器人的 Microsoft 应用 ID。
  5. 应用程序Emulator版本,通过 appid 声明(版本 1 ()或授权方声明(版本 2) )发送 AppId (appId) 。
  6. 该令牌在其有效期内。 行业标准时钟偏差为 5 分钟。
  7. 令牌具有有效的加密签名,包含在步骤 3 中检索到的 OpenID 密钥文档中列出的密钥。

备注

要求 5 是特定于Emulator路径。

如果令牌不满足所有这些要求,则机器人应通过返回 HTTP 403(禁止) 状态代码终止该请求。

重要

所有这些要求都很重要,尤其是要求 4 和 7。 如果未能实现所有这些验证要求将使机器人受到攻击,这可能会导致机器人公开其 JWT 令牌。

模拟器到机器人:示例 JWT 组件

header:
{
  typ: "JWT",
  alg: "RS256",
  x5t: "<SIGNING KEY ID>",
  kid: "<SIGNING KEY ID>"
},
payload:
{
  aud: "<YOUR MICROSOFT APP ID>",
  iss: "https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/",
  nbf: 1481049243,
  exp: 1481053143,
  ... other fields follow
}

备注

在实践中,实际字段可能会有所不同。 创建并验证上面指定的所有 JWT 令牌。

安全协议更改

机器人到 Connector 身份验证

OAuth 登录 URL

协议版本 有效值
v3.1 和 v3.2 https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token

OAuth 作用域

协议版本 有效值
v3.1 和 v3.2 https://api.botframework.com/.default

Connector 到机器人身份验证

OpenID 元数据文档

协议版本 有效值
v3.1 和 v3.2 https://login.botframework.com/v1/.well-known/openidconfiguration

JWT 颁发者

协议版本 有效值
v3.1 和 v3.2 https://api.botframework.com

模拟器到机器人身份验证

OAuth 登录 URL

协议版本 有效值
v3.1 和 v3.2 https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token

OAuth 作用域

协议版本 有效值
v3.1 和 v3.2 机器人的 Microsoft 应用 ID + /.default

JWT 受众

协议版本 有效值
v3.1 和 v3.2 机器人的 Microsoft 应用 ID

JWT 颁发者

协议版本 有效值
v3.1 1.0 https://sts.windows.net/d6d49420-f39b-4df7-a1dc-d59a935871db/
v3.1 2.0 https://login.microsoftonline.com/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0
v3.2 1.0 https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/
v3.2 2.0 https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0

另请参阅 非政府 事例的突出显示值。

OpenID 元数据文档

协议版本 有效值
v3.1 和 v3.2 https://login.microsoftonline.com/botframework.com/v2.0/.well-known/openid-configuration

其他资源