如何用 Amazon Bedrock AgentCore Gateway 实现 ServiceNow 的 OBO token 交换
ServiceNow on-behalf-of token exchange with Bedrock AgentCore Gateway
Amazon Bedrock AgentCore Gateway 可配置 on-behalf-of(OBO)token 交换,使 AI 智能体调用 ServiceNow REST API 时保留发起用户的身份。
代表用户与企业 API 交互的 AI 智能体需要在整个请求链路中维持用户身份。如果没有身份传播,API 调用会以应用程序本身的身份(而非发起操作的用户)到达下游服务。这会破坏审计追踪、绕过用户级访问控制,并违背最小权限原则。
Amazon Bedrock AgentCore 是一个用于大规模构建、连接和优化智能体的平台,支持任何框架或模型。本文介绍如何将 Amazon Bedrock AgentCore 的一项功能 AgentCore Gateway 配置为与 Microsoft Entra ID 进行代表(OBO)令牌交换。这样,AI 智能体就可以在保留调用用户身份的情况下调用 ServiceNow REST API。您在网关目标上配置令牌交换,AgentCore Gateway 会在每次请求时执行该交换。这一模式也可以应用于其他受 OAuth 保护的 REST API。
在生产环境中,您还可以将身份传播与 Amazon Bedrock Guardrails 结合使用,以过滤有害内容并验证智能体的输入和输出。
解决方案概览
该架构包含通过 AgentCore Gateway 连接的三个关键组件:
- 一个 AI 智能体应用程序,通过 OAuth 应用程序注册受 Microsoft Entra ID 保护。
- 一个模型上下文协议(MCP)服务器,使用 AgentCore Gateway 实现,位于智能体与 ServiceNow 之间。
- ServiceNow REST API,配置了与 Microsoft Entra ID 绑定的入站 OAuth 集成。
下图展示了端到端的解决方案架构,包括 AWS、Microsoft Entra ID 和 ServiceNow 中的组件。
图 1:跨 AWS、Microsoft Entra ID 和 ServiceNow 的解决方案架构
如图 1 所示,用户获取一个 JSON Web Token(JWT)来调用智能体 1。智能体使用一个作用域限定为智能体自身应用程序注册的 JWT 令牌向网关进行身份验证 2。然后,网关使用 OBO 流程将该令牌交换为一个新的令牌,其作用域限定为 ServiceNow API 连接器,同时保留原始用户的身份 3。ServiceNow 收到一个有效令牌,其 preferred_username 声明映射到现有的 ServiceNow 用户,并将该用户的权限应用于 API 调用 4。
OBO 令牌交换在此场景中的工作原理
当智能体调用网关时,它提交的 JWT 包含一个与智能体客户端 ID 匹配的 audience 声明(例如 3ff88e17-XXXX-XXXX-XXXX-XXXXXXXXXXXX)。然而,ServiceNow 期望收到一个 audience 声明与其自身 API 连接器客户端 ID(5d4a7a11-XXXX-XXXX-XXXX-XXXXXXXXXXXX)匹配的令牌。
OBO 流程弥补了这一差距。AgentCore Gateway 将入站令牌连同智能体应用程序的客户端凭据、目标作用域以及参数 requested_token_use: on_behalf_of 一起发送到 Entra 令牌端点。Entra 验证调用用户已同意该委托,然后为 ServiceNow API 签发一个新令牌,并完整保留原始用户的声明。
前提条件
开始之前,您需要具备以下条件:
- 一个可以访问 AgentCore Gateway 的 AWS 账户。
- 一个有权创建 应用程序注册 的 Microsoft Entra ID 租户。您的账户至少需要 Application Developer 角色 才能注册应用程序。
- 一个具有管理权限的 ServiceNow 实例,用于配置入站 OAuth 集成。您可以在 ServiceNow 个人开发人员实例注册页面 https://developer.servicenow.com/ 创建 ServiceNow 个人开发人员实例(PDI)。
- 两个 Entra 应用程序注册:一个代表 AI 智能体,另一个代表 ServiceNow API 连接器。
配置 Microsoft Entra ID
首先创建一个应用程序注册来代表 ServiceNow API 连接器。以下屏幕截图显示了 Microsoft Entra ID 中 ServiceNow API 连接器的应用程序注册页面。
图 2:Microsoft Entra ID 中 ServiceNow API 连接器的应用程序注册
创建完成后,在“概述”页面记下 应用程序(客户端)ID。
在导航菜单中展开 管理,选择 公开 API,并使用默认的应用程序 ID URI 添加一个名为 user_impersonation 的作用域。这个作用域就是 OBO 流程在交换令牌时所请求的内容。以下屏幕截图显示了如何在 Microsoft Entra ID 中公开 API。
图 3:在 Microsoft Entra ID 中公开 user_impersonation 作用域
接下来,为 AI 智能体创建一个应用程序注册。以下屏幕截图显示了 Microsoft Entra ID 中 ServiceNow Agent 应用程序的应用程序注册页面。
图 4:Microsoft Entra ID 中 ServiceNow Agent 的应用程序注册
记下 ServiceNow Agent 的应用程序(客户端)ID。
在此注册上创建一个客户端密码。网关需要这些凭据来执行 OBO 交换。以下屏幕截图显示了如何在 Microsoft Entra ID 中的 ServiceNow Agent 应用程序注册上创建客户端密码。
图 5:在 ServiceNow Agent 应用程序注册上创建客户端密码
然后,将智能体应用程序配置为具有调用 ServiceNow API 连接器应用程序的 API 权限。以下屏幕截图显示了需要在 Microsoft Entra ID 中的 ServiceNow Agent 应用程序注册上配置的 API 权限。
图 6:Microsoft Entra ID 中的 API 权限配置
除了在任意标准的两个应用程序之间的 OBO 集成中所需的设置之外,无需对 Entra 配置做任何更改。
配置 ServiceNow
在 ServiceNow 管理控制台中,导航到 System OAuth > 入站集成,并创建一个新的入站集成(由支持 OIDC 的身份提供程序颁发的第三方 ID 令牌)。指定你在 Entra 中创建的 ServiceNow API 连接器应用程序注册的客户端 ID。以下屏幕截图显示了 ServiceNow 中入站集成的配置。
图 7:在 ServiceNow 中配置入站集成
在同一屏幕中,创建一个新的 OpenID Connect (OIDC) 提供程序配置,并输入你的 Entra 租户的 OIDC 元数据 URL。将用户声明映射到相应的用户字段。例如,如果你的 Entra 租户将用户电子邮件放在 preferred_username 声明中,则将其映射到 ServiceNow 中的 Email 字段。如果你的 Entra 租户在令牌中不包含 JTI 验证,请清除 JTI 验证。Entra 在其颁发的令牌上使用一个名为 uti 的内部声明,它等同于 JTI。可以考虑将这个 uti 声明映射到 jti 声明,以提供额外的重放保护和拒绝列表功能。以下屏幕截图显示了如何在 ServiceNow 中配置 OIDC 提供程序。
图 8:在 ServiceNow 中配置 OAuth OIDC 提供程序
最后,在同一屏幕中,为该集成创建一个授权作用域(例如 APIConnector)。以下屏幕截图显示了如何在 ServiceNow 中创建新的授权作用域。
图 9:在 ServiceNow 中创建新的授权作用域
将授权范围限制为 Table API,或你的智能体需要访问的任意 ServiceNow API,如下方截图所示。
图 10:在 ServiceNow 中将授权范围限制为 Table API
此配置完成后,ServiceNow 将接受带有你 API 连接器客户端 ID 的 audience 的授权令牌,并从 preferred_username 声明中解析调用用户。
配置 AgentCore Gateway
在 Entra 和 ServiceNow 配置完毕后,你现在可以设置 AgentCore Gateway 来原生处理 OBO 交换。
第 1 步:创建出站授权配置
在 AgentCore 中创建一个新的出站授权配置(选择 Build > Identity > Add Outbound Auth > Add OAuth client),并选择 Customized provider。输入来自你的智能体应用注册的客户端 ID 和客户端密钥,以及 Entra 发现 URL,如下方截图所示。
图 11:在 AgentCore Gateway 中添加 OAuth 客户端
展开 Additional configurations,并按下方截图所示选择 JWT authorization grant。这会告诉网关在令牌交换时使用基于 JWT 的授权类型。
图 12:配置 JWT authorization grant
第 2 步:使用 MCP 版本 2025-11-25 创建网关
创建一个新的 AgentCore Gateway(Build > Gateways > Create gateway)。在定义网关详细信息时,展开 Additional configurations — optional,并按下方截图所示选择 MCP 版本 2025-11-25。原生 OBO 支持需要此版本。对于使用更早 MCP 版本创建的网关,无法开启原生 OBO。
图 13:选择 MCP 版本 2025-11-25
使用你的智能体应用注册来配置入站身份(选择 Use existing identity provider configurations),就像为任何接受 Entra 身份验证请求的网关所做的那样。
在 JWT Authorization Configuration 下,添加我们之前为 ServiceNowAgent 记录的 Application ID,如下方截图所示。
图 14:在 AgentCore Gateway 中配置入站授权
第 3 步:添加带令牌交换的目标
向网关添加一个指向你的 ServiceNow REST 端点的目标。以内联方式定义 schema。例如,要暴露一个名为 ListIncidents 的工具来调用 ServiceNow Table API,你可以使用以下 OpenAPI 规范(将服务器 URL 替换为你的 PDI 的 URL)。
{
"openapi": "3.0.0",
"info": {
"title": "ServiceNow Incident API (Minimal)",
"description": "A subset of the ServiceNow Table API for listing incident records.",
"version": "1.0.0"
},
"servers": [
{
"url": "https://devxxx.service-now.com/api/now/table",
"variables": {
"instance": {
"default": "devxxx",
"description": "Your ServiceNow instance name."
}
}
}
],
"paths": {
"/incident": {
"get": {
"operationId": "getIncidents",
"summary": "List incidents",
"description": "Retrieves a list of incident records from the ServiceNow instance.",
"parameters": [
{
"name": "sysparm_limit",
"in": "query",
"description": "Maximum number of records to return.",
"schema": {
"type": "integer",
"default": 10
}
},
{
"name": "sysparm_query",
"in": "query",
"description": "An encoded query string to filter results (e.g., active=true).",
"schema": {
"type": "string"
}
},
{
"name": "sysparm_fields",
"in": "query",
"description": "A comma-separated list of fields to return.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "A successful response containing an array of incidents.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"result": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Incident"
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized - Invalid credentials."
}
},
"security": [
{
"bearerAuth": []
}
]
}
}
},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
},
"schemas": {
"Incident": {
"type": "object",
"properties": {
"sys_id": {
"type": "string",
"description": "Unique identifier for the incident."
},
"number": {
"type": "string",
"description": "Incident ID (e.g., INC0000001)."
},
"short_description": {
"type": "string",
"description": "A brief summary of the incident."
},
"severity": {
"type": "string",
"description": "The severity level of the incident."
},
"state": {
"type": "string",
"description": "The current state of the incident (e.g., New, In Progress, Closed)."
},
"sys_created_on": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the incident was created."
}
}
}
}
}
}下方截图展示了如何在 AgentCore Gateway 中使用 OpenAPI schema 配置 REST API 目标。
图 15:使用 ServiceNow OpenAPI schema 配置 REST API 目标
对于目标上的 Outbound Auth configuration,选择 OAuth 作为出站身份提供方,并选择你在第 1 步中创建的出站授权配置。
现在展开 Additional configurations 部分,并选择 Token exchange grant。配置以下内容:
Scope:api://5d4a7a11-xxxx-xxxx-xxxx-xxxxxxxxxxxx/user_impersonation
这是你在 Entra 中的 ServiceNow API 连接器应用注册上暴露的 scope。
Custom parameter(键值对):requested_token_use:on_behalf_of
此参数至关重要。没有它,Entra 就不会执行 OBO 交换,对 ServiceNow 的调用将因身份验证错误而失败。
最终配置如下方截图所示。
图 16:AgentCore Gateway 目标上的 Token exchange grant 配置
第 4 步:保存并测试
保存目标配置。AgentCore Gateway 现在会自动将入站令牌交换为有效的 ServiceNow 令牌,同时保留用户身份,无需任何自定义代码。
当智能体调用网关时,以下过程会透明地发生:
- 网关接收智能体的 JWT(
audience:智能体客户端 ID)。 - 网关使用 OBO 授权类型将该令牌发送到 Entra 的令牌端点。
- Entra 签发一个新令牌(
audience:ServiceNow API 连接器客户端 ID),其中包含原始用户的声明。 - 网关将使用交换后的令牌的请求转发给 ServiceNow。
- ServiceNow 从令牌中解析出用户并应用其权限。
以下代码片段展示了一个通过 MCP 服务器与 ServiceNow 交互的最小化聊天智能体。
import sys
import strands
from strands.models import BedrockModel
from strands.tools.mcp import MCPClient
from mcp.client.streamable_http import streamablehttp_client
token = sys.argv[1] if len(sys.argv) > 1 else sys.exit("Usage: python snow_agent.py <TOKEN>")
MCP_URL = "<GATEWAY_URL>"
mcp_client = MCPClient(lambda: streamablehttp_client(url=MCP_URL, headers={"Authorization": f"Bearer {token}"}))
agent = strands.Agent(
model=BedrockModel(model_id="global.anthropic.claude-sonnet-4-6", streaming=False),
system_prompt=(
"You have a tool called 'target-snow___getIncidents'. "
"When asked about incidents, call it immediately with no parameters. "
"Never ask the user for credentials or instance details --- the tool is pre-configured."
),
tools=[mcp_client],
)
while (user_input := input("\nYou: ")).lower() not in ("quit", "exit", "q"):
print(f"\nAgent: {agent(user_input)}")故障排除
如果收到来自 ServiceNow 的身份验证错误,请验证:
- 交换后令牌中的
preferred_username声明是否映射到 ServiceNow 中的有效用户电子邮件。 - ServiceNow 入站集成上的授权范围是否允许访问你的智能体正在调用的 API 端点。
- 智能体应用程序是否在 Entra 中拥有对 ServiceNow API 连接器应用程序的 API 权限。
清理
为避免持续产生费用,如果你为测试创建了以下资源,请将其删除:
- AgentCore Gateway 及其目标。
- 出站授权配置。
- Entra 应用程序注册(如果专门为本演练创建)。
- ServiceNow 入站集成和 OIDC 提供商配置。
结论
AgentCore Gateway 的原生 OBO 支持免除了使用自定义 AWS Lambda 拦截器执行令牌交换的需要。你直接在网关目标上配置令牌交换,网关会在每次请求时透明地处理它。这种方式在整个智能体到 API 的链路中保留用户身份,支持 ServiceNow 的用户级访问控制,并消除了需要单独维护的自定义代码。
要开始使用 AgentCore Gateway,请参阅 Amazon Bedrock AgentCore 文档。有关 Microsoft Entra 的 OBO 流程的更多信息,请参阅 Microsoft 标识平台文档。
关于作者
来源: AWS Machine Learning Blog · aws.amazon.com















