使用 Bot Connector API 进行身份验证
机器人使用通过安全通道 (SSL/TLS) 的 HTTP 与 Bot Connector 服务进行通信。 当机器人向 Connector 服务发送请求时,它必须包含 Connector 服务可以用来验证其身份的信息。 同样,当 Connector 服务向机器人发送请求时,它必须包含机器人可以用来验证其身份的信息。 本文介绍在机器人和 Bot Connector 服务之间进行的服务级身份验证的身份验证技术和要求。 如果正在编写自己的身份验证代码,必须实现本文所述的安全过程,以便机器人能够与 Bot Connector 服务交换消息。
重要
如果正在编写自己的身份验证代码,则必须正确实现所有安全程序。 通过实现本文中的所有步骤,可以降低攻击者能够读取发送到机器人的消息、发送模拟机器人的消息以及窃取密钥的风险。
如果使用的是 Bot Framework SDK,则不需要实现本文所述的安全程序,因为 SDK 会自动为你完成。 只需使用在注册期间为机器人获得的应用 ID 和密码配置项目,SDK 将处理其余部分。
身份验证技术
四个身份验证技术用于在机器人和 Bot Connector 之间建立信任:
技术 | 说明 |
---|---|
SSL/TLS | SSL/TLS 适用于所有服务到服务连接。 X.509v3 证书用于建立所有 HTTPS 服务的标识。 客户端应始终检查服务证书以确保它们受信任且有效。 (客户端证书不作为此方案的一部分使用。) |
OAuth 2.0 | OAuth 2.0 使用 Microsoft Entra ID 帐户登录服务,生成机器人可用于发送消息的安全令牌。 此令牌是服务到服务令牌;无需用户登录。 |
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
若要获取和使用机器人的 JWT 令牌:
- 机器人将 GET HTTP 请求发送到 MSA 登录服务。
- 来自服务的响应包含要使用的 JWT 令牌。
- 机器人在向 Bot Connector 服务发出的请求中的授权标头内包含此 JWT 令牌。
步骤 1:从 Microsoft Entra ID 帐户登录服务请求访问令牌
重要
如果尚未这样做,则必须向 Bot Framework 注册机器人以获取其应用 ID 和密码。 若要请求访问令牌,需要机器人的应用 ID 和密码。
可以通过几种不同的方式在 Azure 中管理机器人标识。
- 作为用户分配的托管标识,因此无需自行管理机器人的凭据。
- 作为单租户应用。
- 作为多租户应用。
根据机器人的应用程序类型请求访问令牌。
若要从登录服务请求访问令牌,请发出以下请求,将 MICROSOFT-APP-ID 和 MICROSOFT-APP-PASSWORD 替换为向机器人服务注册机器人时获得的机器人应用 ID 和密码。
POST https://login.partner.microsoftonline.cn/botframework.com/oauth2/v2.0/token
Host: login.partner.microsoftonline.cn
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.azure.cn%2F.default
步骤 2:从 Microsoft Entra ID 帐户登录服务响应获取 JWT 令牌
如果应用程序已由登录服务授权,那么 JSON 响应正文将指定访问令牌、其类型及其过期时间(以秒为单位)。
将令牌添加到请求的 Authorization
标头时,必须使用此响应中指定的确切值(即,不转义或编码令牌值)。 访问令牌有效,直到过期。 为了防止令牌过期影响机器人性能,可以选择缓存并主动刷新令牌。
此示例显示来自 Microsoft Entra ID 帐户登录服务的响应:
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
标头中包含访问令牌。
如果令牌格式正确、未过期且其由 Microsoft Entra ID 帐户登录服务生成,则 Bot Connector 服务将对请求授权。 需执行额外检查以确保令牌属于发送请求的机器人。
下面的示例演示如何指定请求 Authorization
标头中的访问令牌。
POST https://smba.trafficmanager.net/teams/v3/conversations/12345/activities
Authorization: Bearer eyJhbGciOiJIUzI1Ni...
(JSON-serialized Activity message goes here)
重要
只在发送到 Bot Connector 服务的请求的 Authorization
标头中指定 JWT 令牌。
不要将令牌发送到非安全通道,也不要将其包含在发送给其他服务的 HTTP 请求中。
从 Microsoft Entra ID 帐户登录服务获取的 JWT 令牌类似于密码,应谨慎处理。 拥有令牌的任何人都可以使用它代表机器人执行操作。
机器人到 Connector:示例 JWT 组件
header:
{
typ: "JWT",
alg: "RS256",
x5t: "<SIGNING KEY ID>",
kid: "<SIGNING KEY ID>"
},
payload:
{
aud: "https://api.botframework.azure.cn",
iss: "https://sts.chinacloudapi.cn/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 服务的调用进行身份验证。
若要对来自 Bot Connector 服务的调用进行身份验证:
- 机器人从自 Bot Connector 服务发出的请求中的授权标头内获取 JWT 令牌。
- 机器人获取 Bot Connector 服务的 OpenID 元数据文档。
- 机器人从文档获取有效的签名密钥列表。
- 机器人验证 JWT 令牌的真实性。
步骤 2:获取 OpenID 元数据文档
OpenID 元数据文档指定第二个文档的位置,其中列出了 Bot Connector 服务的有效签名密钥。 若要获取 OpenID 元数据文档,请通过 HTTPS 发出此请求:
GET https://login.botframework.azure.cn/v1/.well-known/openidconfiguration
提示
这是静态 URL,可以硬编码到应用程序。
下面的示例演示响应 GET
请求返回的 OpenID 元数据文档。 jwks_uri
属性指定包含 Bot Connector 服务的有效签名密钥的文档的位置。
{
"issuer": "https://api.botframework.azure.cn",
"authorization_endpoint": "https://invalid.botframework.azure.cn",
"jwks_uri": "https://login.botframework.azure.cn/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.azure.cn/v1/.well-known/keys
响应正文指定 JWK 格式的文档,还包括每个密钥的其他属性:endorsements
。
提示
密钥列表是稳定的,可以缓存,但随时可能会有新密钥添加到其中。 为了确保在使用这些密钥之前机器人有文档的最新副本,所有机器人实例应至少每 24 小时刷新一次文档的本地缓存。
每个密钥中的 endorsements
属性包含一个或多个字符串,可用于验证在传入请求的 Activity 对象的 channelId
属性中定义的通道 ID 是否可信。 需要认可的通道 ID 列表在每个机器人中都可配置。 默认情况下,它将是所有已发布通道 ID 的列表,尽管机器人开发人员可能会通过任何一种方式重写选定通道的 ID 值。
步骤 4:验证 JWT 令牌
若要验证由 Bot Connector 服务发送的令牌的真实性,必须从请求的 Authorization
标头中提取令牌、分析令牌、验证其内容并验证其签名。
JWT 分析库适用于许多平台,并且大多数对 JWT 令牌实现安全且可靠的分析,尽管通常情况下必须配置这些库以请求令牌的某些特征(其颁发者、受众等)包含正确的值。 分析令牌时,必须配置分析库或编写你自己的验证来确保令牌满足这些要求:
- 令牌在 HTTP
Authorization
标头中使用“持有者”方案发送。 - 令牌是有效的 JSON,符合 JWT 标准。
- 令牌包含值为
https://api.botframework.azure.cn
的“颁发者”声明。 - 该令牌包含一个“受众”声明,其值等于机器人的 Microsoft 应用 ID。
- 该令牌在其有效期内。 行业标准时钟偏差为 5 分钟。
- 令牌具有有效的加密签名,包含在步骤 3 中检索到的 OpenID 密钥文档中列出的密钥,使用的是步骤 2 中检索到的 Open ID 元数据文档的
id_token_signing_alg_values_supported
属性中指定的签名算法。 - 该令牌包含“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.azure.cn",
nbf: 1481049243,
exp: 1481053143,
... other fields follow
}
注意
在实践中,实际字段可能会有所不同。 创建并验证上面指定的所有 JWT 令牌。
对从 Bot Framework Emulator 到机器人的请求进行身份验证
Bot Framework Emulator 是一个桌面工具,可用于测试机器人的功能。 虽然 Bot Framework Emulator 使用如上所述的相同身份验证技术,但它无法模拟真实的 Bot Connector 服务。
与之相反,它使用在将 Emulator 连接到机器人时所指定的 Microsoft 应用 ID 和 Microsoft 应用密码,以创建与机器人创建的令牌相同的令牌。
在 Emulator 向机器人发送请求时,它将在请求的 Authorization
标头中指定 JWT 令牌,从本质上讲,这是使用机器人自己的凭据对请求进行身份验证。
如果要实现身份验证库,并想要接受来自 Bot Framework Emulator 的请求,则必须添加此附加验证路径。 此路径在结构上类似于 Connector -> Bot 验证路径,但它使用 MSA 的 OpenID 文档而不是 Bot Connector 的 OpenID 文档。
如要对从 Bot Framework Emulator 的调用进行身份验证:
- 机器人从自 Bot Framework Emulator 发出的请求中的授权标头内获取 JWT 令牌。
- 机器人获取 Bot Connector 服务的 OpenID 元数据文档。
- 机器人从文档获取有效的签名密钥列表。
- 机器人验证 JWT 令牌的真实性。
步骤 2:获取 MSA OpenID 元数据文档
OpenID 元数据文档指定第二个文档的位置,其中列出了有效签名密钥。 若要获取 MSA OpenID 元数据文档,请通过 HTTPS 发出此请求:
GET https://login.partner.microsoftonline.cn/botframework.com/v2.0/.well-known/openid-configuration
下面的示例演示响应 GET
请求返回的 OpenID 元数据文档。 jwks_uri
属性指定文档的位置,其中包含有效的签名密钥。
{
"authorization_endpoint":"https://login.partner.microsoftonline.cn/common/oauth2/v2.0/authorize",
"token_endpoint":"https://login.partner.microsoftonline.cn/common/oauth2/v2.0/token",
"token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt"],
"jwks_uri":"https://login.partner.microsoftonline.cn/common/discovery/v2.0/keys",
...
}
步骤 3:获取有效签名密钥的列表
若要获取有效的签名密钥列表,请通过 HTTPS 向 OpenID 元数据文档中的 jwks_uri
属性指定的 URL 发出 GET
请求。 例如:
GET https://login.partner.microsoftonline.cn/common/discovery/v2.0/keys
Host: login.partner.microsoftonline.cn
响应正文指定 JWK 格式的文档。
步骤 4:验证 JWT 令牌
若要验证 Emulator 发送的令牌的真实性,必须从请求的 Authorization
标头提取令牌,分析令牌,验证其内容,然后验证其签名。
JWT 分析库适用于许多平台,并且大多数对 JWT 令牌实现安全且可靠的分析,尽管通常情况下必须配置这些库以请求令牌的某些特征(其颁发者、受众等)包含正确的值。 分析令牌时,必须配置分析库或编写你自己的验证来确保令牌满足这些要求:
- 令牌在 HTTP
Authorization
标头中使用“持有者”方案发送。 - 令牌是有效的 JSON,符合 JWT 标准。
- 令牌包含一个“颁发者”声明,其中包含非政府案例的突出显示值之一。 检查两个颁发者值将确保检查安全协议 v3.1 和 v3.2 颁发者值。
- 该令牌包含一个“受众”声明,其值等于机器人的 Microsoft 应用 ID。
- Emulator 会根据版本通过 appid 声明(版本 1)或授权方声明(版本 2)发送 AppId。
- 该令牌在其有效期内。 行业标准时钟偏差为 5 分钟。
- 令牌具有有效的加密签名,包含在步骤 3 中检索到的 OpenID 密钥文档中列出的密钥。
注意
要求 5 特定于 Emulator 验证路径。
如果令牌不满足所有这些要求,则机器人应通过返回“HTTP 403(禁止)”状态代码终止该请求。
重要
所有这些要求都很重要,尤其是要求 4 和 7。 如果未能实现所有这些验证要求将使机器人受到攻击,这可能会导致机器人公开其 JWT 令牌。
Emulator 到机器人:示例 JWT 组件
header:
{
typ: "JWT",
alg: "RS256",
x5t: "<SIGNING KEY ID>",
kid: "<SIGNING KEY ID>"
},
payload:
{
aud: "<YOUR MICROSOFT APP ID>",
iss: "https://sts.chinacloudapi.cn/d6d49420-f39b-4df7-a1dc-d59a935871db/",
nbf: 1481049243,
exp: 1481053143,
... other fields follow
}
注意
在实践中,实际字段可能会有所不同。 创建并验证上面指定的所有 JWT 令牌。
安全协议更改
机器人到 Connector 身份验证
OAuth 登录 URL
协议版本 | 有效值 |
---|---|
v3.1 和 v3.2 | https://login.partner.microsoftonline.cn/botframework.com/oauth2/v2.0/token |
OAuth 作用域
协议版本 | 有效值 |
---|---|
v3.1 和 v3.2 | https://api.botframework.azure.cn/.default |
Connector 到机器人身份验证
OpenID 元数据文档
协议版本 | 有效值 |
---|---|
v3.1 和 v3.2 | https://login.botframework.azure.cn/v1/.well-known/openidconfiguration |
JWT 颁发者
协议版本 | 有效值 |
---|---|
v3.1 和 v3.2 | https://api.botframework.azure.cn |
Emulator 到机器人身份验证
OAuth 登录 URL
协议版本 | 有效值 |
---|---|
v3.1 和 v3.2 | https://login.partner.microsoftonline.cn/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.chinacloudapi.cn/d6d49420-f39b-4df7-a1dc-d59a935871db/ |
v3.1 2.0 | https://login.partner.microsoftonline.cn/d6d49420-f39b-4df7-a1dc-d59a935871db/v2.0 |
v3.2 1.0 | https://sts.chinacloudapi.cn/f8cdef31-a31e-4b4a-93e4-5f571e91255a/ |
v3.2 2.0 | https://login.partner.microsoftonline.cn/f8cdef31-a31e-4b4a-93e4-5f571e91255a/v2.0 |
另请参阅非政府案例的突出显示值之一。
OpenID 元数据文档
协议版本 | 有效值 |
---|---|
v3.1 和 v3.2 | https://login.partner.microsoftonline.cn/botframework.com/v2.0/.well-known/openid-configuration |