Bedrock AgentCore Web Search Tool 配置 JWT 认证集成到 Kiro

本文介绍了 Kiro CLI 通过 MCP 协议集成 Amazon Bedrock AgentCore Web Search Tool 作为联网搜索引擎的方法。针对开发者本机没有 IAM User 密钥的场景,方案将 AgentCore Gateway 配置为 CUSTOM_JWT 认证,以 Amazon Cognito 为身份提供商,采用 OAuth 2.0 授权码加 PKCE 浏览器跳转认证,全程无须在本机保存长期密钥,并记录了回调地址格式与 scope 一致性两个实测要点。

一、背景

很多开发工具包括 Claude Code、Codex、Kiro、乃至 Amazon Quick 都可以使用 EXA Search 提供的 MCP Server 作为搜索引擎。在上文中,我们搭建好了 Bedrock AgentCore Web Search Tool,由此可以使用 AgentCore 提供的搜索能力来替换 EXA Search 作为搜索工具提供商。这样做的好处是,整个数据流在 AWS 平台上完全闭环,数据不出 AWS,无须为引入别的供应商而重新评估数据安全边界。

本文介绍 Kiro 集成 Bedrock AgentCore Web Search Tool 的方法,主要难点在于选择合适的身份认证方案。本文的操作对象为 Kiro CLI,并要求将其升级到最新版本(下文使用的 OAuth 配置能力以最新版本为准);Kiro IDE 的 MCP 面板认证流程与 CLI 存在差异,不在本文讨论范围内。

二、Kiro 以 MCP 协议集成 Bedrock AgentCore Gateway 的认证方案选择

1、Bedrock AgentCore Gateway 支持的认证方式

Bedrock AgentCore Web Search Tool 搜索功能自身不是直接作为网络服务被调用的,而是集成在 Bedrock AgentCore Gateway 这个网关上,并且通过 AgentCore Gateway 网关调用,是唯一的调用方式。因此开发客户端 Claude Code、Codex、Kiro、乃至 Amazon Quick,都需要用 MCP 协议连接到 AgentCore Gateway 网关,才可以进一步调用搜索服务。

AgentCore Gateway 网关支持如下几种认证:

  • IAM 身份认证:即 AWS_IAM。调用方使用 AWS IAM 身份的凭证,请求需带 SigV4 签名。Gateway 会校验调用方是否具备 bedrock-agentcore:InvokeGateway 权限。
  • JWT 令牌认证,即 CUSTOM_JWT,OAuth。由外部身份提供商(如 Amazon Cognito、Okta、Auth0 等支持 OIDC 的提供商)签发 JWT,调用方携带 Bearer Token,Gateway 校验其有效性、audience、scope 等声明。
  • Offloaded(授权下放)类型,Gateway 本身不做鉴权决策,共两种子类型:
    • Authenticate only(AUTHENTICATE_ONLY):Gateway 仍会校验调用方的 SigV4 签名以确认身份,但不做任何授权判断,任何签名有效的 IAM 主体都会被转发到 Target,授权逻辑需要下游 Target 或附加的策略引擎(Policy Engine)来完成。
    • No Authorization(NONE):Gateway 对入站请求不做任何鉴权,请求可以是完全未认证的。

以上几种身份认证类型做小结:方式 1 适合在 AWS 云上服务之间调用,方式 2 适合第三方 SaaS 对接中的调用,方式 3 适合网关托管的下级服务自己有认证机制的场景。

2、在开发者本机没有 IAM User 密钥场景下的认证选择

上一篇博客介绍的是使用 Strands Agents 开发一个 Agent,调用 AgentCore Web Search Tool,整个工作链条都是基于 AWS 云服务,因此选择 IAM 身份认证作为 AgentCore Gateway 的决策就非常合理。但是,针对 Kiro 开发工具的对接,使用 IAM 认证方式有所不足。Kiro 作为开发工具运行在开发者本机,开发者不一定有 AWS IAM User 的 Access Key/Secret Key。这是因为在大型企业中有着严格的安全管理机制,且不一定实现 DevOps 自动化部署和运维。因此 IAM 身份认证对于非系统管理员级别的一般开发者其实是很不方便的。

因此,不选择 IAM 认证方式、将 AgentCore Gateway 配置为 JWT 认证时候,认证过程不依赖于 AWS IAM User 账号体系。此时需要配置第三方认证服务,例如 AWS 云上的 Amazon Cognito 认证服务,或者第三方的 SSO 服务如 Okta 等。本文以 Amazon Cognito 为例,采用 OAuth 2.0 的 Authorization Code(授权码)+ PKCE 跳转认证方式:Kiro 打开系统浏览器跳转到 Cognito 登录页,开发者输入账号密码完成登录后换取 Token,Token 过期后由 Refresh Token 自动静默续期,全程无需在本机保存任何长期密钥。

这里说明一个方案取舍:JWT 体系下还有一种面向机器对机器(M2M)的 Client Credentials 授权方式,可以用 Client ID 加 Client Secret 直接换取 Bearer Token 并硬编码到配置文件中,看似省去了浏览器登录环节。但 Cognito 签发的 Access Token 有效期上限仅为 24 小时(默认 3600 秒),且 Client Credentials 流程不发放 Refresh Token,Token 过期后必须重新生成并手工更新配置文件。这种方式无法作为长期静态凭据使用,维护负担反而更重,因此本文不采用,统一使用带自动续期能力的授权码跳转方式。

3、本文讲解内容

本文按照 AgentCore Gateway 使用 JWT 认证的方案,第三章讲解配置 Amazon Cognito 认证服务,第四章配置 AgentCore Gateway 与 Web Search Tool,第五章完成 Kiro 侧配置并验证。

三、配置 Amazon Cognito 认证服务

本章创建 Kiro 认证所需的全部 Cognito 资源:用户池、Hosted UI 域名、应用客户端与测试用户。注:本文的 AgentCore Gateway 需要配置 JWT 认证方式,上一篇博客中基于 AWS_IAM 认证的 Gateway 不可复用,第四章会重新部署一个。

先设置公共变量,本章与第四章的命令均复用这些变量。区域固定为 us-east-1(Web Search Tool 目前仅在该区域可用):

REGION="us-east-1"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ROLE_NAME="AgentCoreWebSearchKiroGatewayRole"
GATEWAY_NAME="websearch-kiro-jwt-gateway"
USER_POOL_NAME="websearch-kiro-pool"
COGNITO_DOMAIN_PREFIX="websearch-kiro-${ACCOUNT_ID}"

1、创建 Cognito 用户池

USER_POOL_ID=$(aws cognito-idp create-user-pool \
  --pool-name "$USER_POOL_NAME" \
  --region "$REGION" \
  --query 'UserPool.Id' --output text)
echo "USER_POOL_ID=$USER_POOL_ID"

返回结果类似如下(形如 us-east-1_xxxxxxxxx):

USER_POOL_ID=us-east-1_o2qx89QGH

2、为用户池配置 Hosted UI 域名

Cognito 的 OAuth 2.0 授权端点(/oauth2/authorize)与令牌端点(/oauth2/token)都挂载在这个域名下,浏览器跳转登录依赖授权端点,Kiro 换取 Token 依赖令牌端点。域名前缀需要在 Cognito 命名空间内全局唯一,这里用账号 ID 拼接以降低冲突概率。另外,命令中显式指定 --managed-login-version 1,即使用经典 Hosted UI 版本的登录页:版本 1 无需额外配置即可直接使用;若使用新版 Managed Login(版本 2),必须先为应用客户端创建 branding style,否则浏览器打开登录页时无法渲染。为控制演示步骤数量,这里选择版本 1:

aws cognito-idp create-user-pool-domain \
  --domain "$COGNITO_DOMAIN_PREFIX" \
  --user-pool-id "$USER_POOL_ID" \
  --managed-login-version 1 \
  --region "$REGION"

命令执行成功后回显所设置的托管登录版本:

{
    "ManagedLoginVersion": 1
}

域名创建后需要几分钟才能生效(实测创建后立即查询 describe-user-pool-domain 即已返回 ACTIVE,但建议仍预留生效时间),最终形成的 Hosted UI 根地址为:

https://${COGNITO_DOMAIN_PREFIX}.auth.${REGION}.amazoncognito.com

3、创建应用客户端(Public Client)与测试用户

Kiro CLI 是运行在开发者本机的 CLI 工具,属于 OAuth 规范中的"公有客户端(Public Client)",即无法安全保存 Client Secret 的客户端类型(Secret 写在本机配置文件里等同于没有保密性)。因此本节创建的 Cognito 应用客户端不生成 Client Secret,转而使用 PKCE(Proof Key for Code Exchange,一种在授权请求和令牌兑换请求之间绑定一次性密钥对的机制)来防止授权码被截获后被冒用。这是 OAuth 2.0 官方针对原生应用、CLI 工具的推荐做法,Kiro CLI 对 PKCE 是原生支持的,无需额外配置。

(1) 创建应用客户端(不生成 Secret)

Kiro 在认证时会在本机 localhost 上启动回调监听服务(Kiro 出于安全考虑仅允许 localhost 作为回调主机)。实测确认(Kiro CLI 2.12.3,MCP 日志中回调服务器的启动记录形如 Redirect server started on http://localhost:<端口>/oauth/callback):Kiro 侧 oauth.redirectUri 配置为 host:port 形式后,实际监听与发起授权请求时会自动在其后补全 /oauth/callback 路径。而 OAuth 授权码流程要求授权请求中的 redirect_uri 与 IdP 侧预先登记的回调 URL 逐字符精确一致,因此这里在 --callback-urls 中登记的地址为补全路径后的完整 URL,端口与第五章 Kiro 配置保持一致。注意 localhost127.0.0.1 在精确匹配下不等价,两侧不可混用:

CLIENT_ID=$(aws cognito-idp create-user-pool-client \
  --user-pool-id "$USER_POOL_ID" \
  --client-name "kiro-websearch-authcode-client" \
  --allowed-o-auth-flows code \
  --allowed-o-auth-scopes openid email profile \
  --allowed-o-auth-flows-user-pool-client \
  --callback-urls "http://localhost:8080/oauth/callback" \
  --supported-identity-providers COGNITO \
  --prevent-user-existence-errors ENABLED \
  --region "$REGION" \
  --query 'UserPoolClient.ClientId' --output text)
echo "CLIENT_ID=$CLIENT_ID"

命令中没有出现 --generate-secret 参数,因此创建出来的是不带 Client Secret 的公有客户端,符合本节开头的设计原则。--allowed-o-auth-flows code 只开放 Authorization Code 授权类型,不开放 Implicit(隐式授权,已被业界弃用,不建议使用)。

这里放行的 openid email profile 三个标准 scope 有一条硬性约束:必须完整涵盖第四章 Gateway allowedScopes 中配置的全部值(本文为 openid)。这是因为 Kiro 遵循 MCP 授权规范,Gateway 对未认证请求返回 401 时会在 WWW-Authenticate 头中广告其 allowedScopes,Kiro 会把广告的 scope 纳入实际发起的授权请求。实测确认(Kiro CLI 2.12.3):如果 Gateway 广告了某个应用客户端未放行的 scope,Cognito 会在登录后拒绝授权,Kiro 报 OAuth authorization failed: invalid_request - invalid_scope,且 Kiro 配置文件中的 oauthScopes 字段并不能覆盖这一行为。日后如果调整 Gateway 的 allowedScopes,必须同步在本应用客户端上放行新增的 scope。

(2) 创建测试用户

为了避免走完整的邮箱验证注册流程,这里用管理员权限直接创建一个测试用户并设置永久密码,方便后续在浏览器登录页直接使用:

TEST_USERNAME="kiro-tester"
TEST_PASSWORD="<自定义一个满足密码策略的强密码>"

aws cognito-idp admin-create-user \
  --user-pool-id "$USER_POOL_ID" \
  --username "$TEST_USERNAME" \
  --user-attributes Name=email,Value="kiro-tester@example.com" Name=email_verified,Value=true \
  --message-action SUPPRESS \
  --region "$REGION"

aws cognito-idp admin-set-user-password \
  --user-pool-id "$USER_POOL_ID" \
  --username "$TEST_USERNAME" \
  --password "$TEST_PASSWORD" \
  --permanent \
  --region "$REGION"

注意:此处的邮箱地址、用户名、密码仅用于本机验证,测试用户的密码不要复用生产账号密码,也不要把包含密码的命令历史提交到代码仓库。

4、汇总本章需要记录的值

第四章与第五章会直接引用这些值,建议先汇总记录:

名称 用途
User Pool ID $USER_POOL_ID(形如 us-east-1_xxxxxxxxx 第四章配置 Gateway 的 JWT Authorizer
Discovery URL https://cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}/.well-known/openid-configuration 第四章配置 Gateway 的 JWT Authorizer
Hosted UI 域名 https://${COGNITO_DOMAIN_PREFIX}.auth.${REGION}.amazoncognito.com 浏览器跳转登录与令牌兑换
Client ID $CLIENT_ID 第五章 Kiro 配置的 oauth.clientId
测试用户 kiro-tester 及其密码 第五章浏览器登录验证

至此 Cognito 侧准备完毕。下面转向 AgentCore Gateway 的部署。

四、配置 AgentCore Gateway 与 Web Search Tool

Web Search Tool 的唯一调用入口是 AgentCore Gateway。本章创建 Gateway 的 IAM 服务角色、CUSTOM_JWT 认证类型的 Gateway,并挂载 Web Search 目标。

1、创建 AgentCore 需要的 IAM Role

Gateway 出站调用 Web Search 后端时,需要代入一个 IAM 服务角色。信任关系仅允许 bedrock-agentcore.amazonaws.com 代入该角色,权限策略包含 bedrock-agentcore:InvokeGatewaybedrock-agentcore:InvokeWebSearch 两个动作。其中出站调用 Web Search 后端实际必需的是 InvokeWebSearchInvokeGateway 面向 IAM 入站认证场景(本文 Gateway 的入站认证为 JWT,不依赖该动作),保留它是为了与上一篇博客的角色策略保持一致,便于对照。

执行如下命令创建 IAM 角色,写入信任策略,允许 bedrock-agentcore 服务代入该角色:

aws iam create-role \
  --role-name "$ROLE_NAME" \
  --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"bedrock-agentcore.amazonaws.com"},"Action":"sts:AssumeRole"}]}' \
  --description "AgentCore Web Search demo gateway service role (for Kiro JWT auth)"

为该角色写入权限策略,授予调用 Gateway 与 Web Search 的权限。其中 Web Search Tool 的资源 ARN 由 AWS 拥有,account 段固定为 aws

aws iam put-role-policy \
  --role-name "$ROLE_NAME" \
  --policy-name "WebSearchInvokePolicy" \
  --policy-document "{
    \"Version\": \"2012-10-17\",
    \"Statement\": [
      {
        \"Sid\": \"InvokeGateway\",
        \"Effect\": \"Allow\",
        \"Action\": \"bedrock-agentcore:InvokeGateway\",
        \"Resource\": \"arn:aws:bedrock-agentcore:${REGION}:${ACCOUNT_ID}:gateway/*\"
      },
      {
        \"Sid\": \"InvokeWebSearch\",
        \"Effect\": \"Allow\",
        \"Action\": \"bedrock-agentcore:InvokeWebSearch\",
        \"Resource\": \"arn:aws:bedrock-agentcore:${REGION}:aws:tool/web-search.v1\"
      }
    ]
  }"

新建的 IAM 角色需要数秒钟才能完全生效,建议等待 1 分钟左右后再创建 Gateway,以降低 PassRole 校验失败的概率。

2、创建认证为 CUSTOM_JWT 类型的 AgentCore Gateway

Gateway 的 JWT Authorizer 指向第三章用户池的 Discovery URL,allowedScopes 配置为 openid:通过第三章应用客户端换取的 Token 天然携带该 scope,可以通过校验;同时 Gateway 在 401 挑战中广告的 scope 也只有 openid,与应用客户端放行的 scope 保持一致(一致性的重要性见第三章第 3 节的说明)。

注意(设计取舍):这里没有配置 allowedClients 做客户端级限制,代价是该 Cognito 用户池下任何携带 openid scope 的合法 Token 都能通过这个 Gateway 的校验。由于本文创建的用户池是专用于本演示的独立资源,这个代价可以接受;生产环境如果需要更严格的限制,可以用 update-gatewaycustomJWTAuthorizer 中补充 allowedClients 列表(填入第三章的 Client ID)收紧范围。

ROLE_ARN=$(aws iam get-role --role-name "$ROLE_NAME" --query Role.Arn --output text)
DISCOVERY_URL="https://cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}/.well-known/openid-configuration"

aws bedrock-agentcore-control create-gateway \
  --name "$GATEWAY_NAME" \
  --role-arn "$ROLE_ARN" \
  --protocol-type MCP \
  --authorizer-type CUSTOM_JWT \
  --authorizer-configuration "{
    \"customJWTAuthorizer\": {
      \"discoveryUrl\": \"${DISCOVERY_URL}\",
      \"allowedScopes\": [\"openid\"]
    }
  }" \
  --description "Web Search demo gateway for Kiro integration (CUSTOM_JWT inbound auth)" \
  --region "$REGION"

获取 Gateway ID 与状态,等待 status 变为 READY

GATEWAY_ID=$(aws bedrock-agentcore-control list-gateways \
  --region "$REGION" \
  --query "items[?name=='${GATEWAY_NAME}'].gatewayId | [0]" \
  --output text)

aws bedrock-agentcore-control get-gateway \
  --gateway-identifier "$GATEWAY_ID" \
  --region "$REGION" \
  --query '{status:status, gatewayUrl:gatewayUrl}'

返回结果类似如下:

---------------------------------------------------------------------------------------------------------------------
|                                                     GetGateway                                                    |
+---------------------------------------------------------------------------------------------------------+---------+
|                                               gatewayUrl                                                 | status  |
+---------------------------------------------------------------------------------------------------------+---------+
|  https://websearch-kiro-jwt-gateway-pyg2plkw8p.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp     |  READY  |
+---------------------------------------------------------------------------------------------------------+---------+

3、挂载 Web Search Tool

在上一步就绪的 Gateway 上挂载 Web Search 目标,出站凭证复用第 1 小节创建的服务角色。注意:本步骤要求 AWS CLI 版本不低于 2.35.19,否则不支持 Web Search 连接器参数(同上一篇博客的要求):

aws bedrock-agentcore-control create-gateway-target \
  --gateway-identifier "$GATEWAY_ID" \
  --name "web-search" \
  --target-configuration '{"mcp":{"connector":{"source":{"connectorId":"web-search"},"configurations":[{"name":"WebSearch","parameterValues":{}}]}}}' \
  --credential-provider-configurations '[{"credentialProviderType":"GATEWAY_IAM_ROLE"}]' \
  --region "$REGION" \
  --query targetId --output text

命令执行成功后返回目标 ID,形如:

VP1YHEVFU5

查询目标状态,等待其变为 READY

aws bedrock-agentcore-control list-gateway-targets \
  --gateway-identifier "$GATEWAY_ID" \
  --region "$REGION" \
  --query "items[?name=='web-search'].{targetId:targetId, status:status}"

返回结果如下:

[
    {
        "targetId": "VP1YHEVFU5",
        "status": "READY"
    }
]

当显示 READY 即表示 Web Search 目标已可用。

4、汇总本章需要记录的值

名称 用途
IAM 角色 ARN arn:aws:iam::<ACCOUNT_ID>:role/AgentCoreWebSearchKiroGatewayRole Gateway 出站调用 Web Search 后端
Gateway ID $GATEWAY_ID(形如 websearch-kiro-jwt-gateway-xxxxxxxxxx 查询状态、后续排障
Gateway URL get-gateway 返回的 gatewayUrl 第五章 Kiro 配置中的 url 字段
Target ID create-gateway-target 返回的 targetId 目标级别的状态查询与问题定位

注意:本章 Gateway 的入站认证类型为 CUSTOM_JWT,且 allowedScopes 未配合 allowedClients 使用,意味着该 Cognito 用户池下任何携带 openid scope 的合法 Token 都能通过校验,具体安全取舍已在第 2 小节说明。此外,Gateway 本身处于空闲状态不产生额外费用,实际计费发生在调用 Web Search 目标检索时,具体费用构成见 README 中的成本章节。

至此,Cognito 与 Gateway 的基础设施全部就绪。接下来进行 Kiro 侧配置。

五、Kiro 配置与验证测试

1、Kiro 配置

~/.kiro/settings/mcp.json(用户级配置,跨工作区生效)中新增一个远程 MCP Server 条目。如果不是在同一个终端会话内继续操作,先按名字取回第四章创建的 Gateway 地址:

REGION="us-east-1"
GATEWAY_NAME="websearch-kiro-jwt-gateway"

GATEWAY_ID=$(aws bedrock-agentcore-control list-gateways \
  --region "$REGION" \
  --query "items[?name=='${GATEWAY_NAME}'].gatewayId | [0]" \
  --output text)

GATEWAY_URL=$(aws bedrock-agentcore-control get-gateway \
  --gateway-identifier "$GATEWAY_ID" \
  --region "$REGION" \
  --query gatewayUrl --output text)
echo "GATEWAY_URL=$GATEWAY_URL"

oauth.clientId 填入第三章创建的公有客户端 ID,用于跳过 Kiro 默认的 Dynamic Client Registration(DCR,动态客户端注册)尝试——Cognito 不提供 DCR 自注册端点,显式指定 clientId 后,Kiro 会直接以该客户端身份发起认证:

{
  "mcpServers": {
    "agentcore-gateway": {
      "type": "http",
      "url": "https://websearch-kiro-jwt-gateway-pyg2plkw8p.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp",
      "oauth": {
        "clientId": "<第三章创建的 CLIENT_ID>",
        "redirectUri": "localhost:8080",
        "oauthScopes": ["openid", "email", "profile"]
      }
    }
  }
}

字段说明:

  • url:填入上文 $GATEWAY_URL 的值。
  • oauth.clientId:跳过 DCR 所必需,填入 Cognito 应用客户端 ID。
  • oauth.redirectUri:本机回调监听地址,必须填写 host:port 形式(即 localhost:8080),Kiro 会自动补全 /oauth/callback 路径,补全后恰好等于第三章第 3 节在 Cognito 登记的回调 URL。注意:虽然 Kiro CLI 2.12 的官方 changelog 声称 redirectUri 支持带路径的完整 URL,但实测 2.12.3 版本填写完整 URL 会解析失败(MCP 日志报 Could not parse port from oauth.redirectUri (expected "host:port"); falling back to random port.),随后回退到随机端口,导致与 Cognito 登记值不匹配、登录后报 An error was encountered with the requested page 错误,因此本字段务必使用 host:port 形式。本文实测 Kiro CLI 版本为 2.12.3,可执行 kiro-cli --version 确认。
  • oauthScopes:期望请求的 OAuth 授权范围,带上 emailprofile 便于后续扩展读取用户身份信息。需要注意,该字段并非实际请求 scope 的唯一来源:实测表明 Kiro 还会把 Gateway 401 挑战中广告的 scope 纳入授权请求,本文 Gateway 只广告 openid、应用客户端已放行,两侧一致故无冲突;两侧不一致时的报错现象见第三章第 3 节。

注意:本文没有配置 oauth.clientSecret,这与第三章选择公有客户端、依赖 PKCE 而非密钥的设计一致;Kiro CLI 也支持为强制要求密钥的服务配置 clientSecret,但公有客户端方案不需要。

2、验证测试

启动 Kiro CLI 并加载上述配置后,执行 /mcp 命令查看服务器状态:

/mcp

首次连接时,agentcore-gateway 会显示为需要认证的状态,可以直接调用一次工具,或者执行 /mcp auth 主动触发认证:

/mcp auth

Kiro 会打开系统默认浏览器,跳转到 Cognito 的 Hosted UI 登录页,实际打开的授权 URL 形如:

https://websearch-kiro-<ACCOUNT_ID>.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth%2Fcallback&scope=openid+email+profile&code_challenge=<PKCE_CHALLENGE>&code_challenge_method=S256&state=<随机状态值>

用第三章创建的测试用户账号密码登录后,浏览器会跳转回本机的回调地址并显示认证成功页面:

http://localhost:8080/oauth/callback?code=<一次性授权码>&state=<随机状态值>

Kiro 在后台用这个授权码加上 PKCE 校验值,向 Cognito 的令牌端点兑换 Access Token(因为是公有客户端,兑换请求不携带 Client Secret),随后自动把 Token 附加到调用 Gateway 的 Authorization: Bearer 请求头中。重新执行 /mcp 可看到 agentcore-gateway 状态变为已连接,并列出 web-search___WebSearch 工具:

agentcore-gateway   connected   tools: web-search___WebSearch

此时即可在 Kiro 中直接提问触发联网搜索,验证完整链路是否可用。Token 过期后 Kiro 会自动使用 Refresh Token 静默刷新,无需重新走浏览器登录;如果刷新失败或需要切换测试账号,可用 /mcp logout 清除已保存的凭据后重新执行 /mcp auth

注意(排障提示):如果认证过程报错,优先检查三点。第一,Kiro CLI 是否已升级到最新版本(执行 kiro-cli --version 确认)。第二,oauth.redirectUri 是否为 host:port 形式且端口与 Cognito 登记的回调 URL 一致——若误填了完整 URL,Kiro 会回退到随机端口,Cognito 登录后将报 An error was encountered with the requested page。第三,应用客户端的允许 scope 是否包含了 Gateway allowedScopes 广告的全部值——若有缺失,登录后 Kiro 会报 OAuth authorization failed: invalid_request - invalid_scope。排障时可查看 Kiro CLI 的 MCP 日志(位于 ~/.kiro/logs/<会话时间戳>/mcp.log),日志中会记录回调服务器实际监听的地址端口与 OAuth 失败原因。

备注(实测记录):本文全部 CLI 命令已于 2026 年 7 月在 AWS CLI 2.35.19、Kiro CLI 2.12.3 环境下逐条实测通过,并在 Kiro CLI 中完整走通了浏览器登录认证,成功列出工具并触发联网搜索。认证链路细节验证如下:向 Gateway 发送无 Token 请求,返回 401 且 WWW-Authenticate 头广告 scope="openid"(与第四章 allowedScopes 配置一致);模拟授权码 + PKCE 流程取得的 Access Token 其 scope 声明为 openid profile email,命中 allowedScopes 中的 openid;携带该 Token 调用 Gateway 的 tools/list 成功返回 web-search___WebSearch 工具,并实际执行搜索调用返回了完整检索结果,出站链路(Gateway 代入 IAM 服务角色调用 Web Search 后端)验证通过。实测中确认的两个关键行为——redirectUri 必须使用 host:port 形式、应用客户端 scope 必须涵盖 Gateway 广告值——已分别写入第 1 小节字段说明与第三章第 3 节。

3、未来改进

Amazon Cognito 服务可对接外部 IdP,因此更优化的方案是,创建的 Cognito 作为认证服务后,不要在 Cognito 添加本地用户,而是再以外部 IdP 的方式挂载企业现有 SSO 统一认证平台。这样在调用这个 MCP 时候,身份认证跳转页面就是跳转到企业 SSO 认证界面,现有企业用户即可完成认证。

六、参考文档

Bedrock AgentCore Gateway 入站认证配置说明

Bedrock AgentCore CUSTOM_JWT Authorizer 字段说明

Amazon Cognito CreateUserPoolClient API 参考

Kiro CLI MCP 配置文档

Kiro CLI 2.12 Changelog:MCP OAuth 对预注册应用的支持(注意:其中关于完整 URL 形式 redirectUri 的描述与 2.12.3 版本实测行为不符,实际仍需 host:port 形式,见第五章第 1 节)

Kiro CLI Agent 配置参考(OAuth 配置字段)


最后修改于 2026-07-16