View a markdown version of this page

使用入站身份验证和出站身份验证进行身份验证和授权 - 亚马逊基岩 AgentCore

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用入站身份验证和出站身份验证进行身份验证和授权

本节向您介绍如何使用带身份的 OAuth 和 JWT 持有者令牌为代理运行时实现身份验证和授权。 AgentCore 您将学习如何设置 Cognito 用户池、为 JWT 身份验证(入站身份验证)配置代理运行时以及如何实现对第三方资源的 OAuth-based 访问权限(出站身份验证)。

有关完整示例,请参阅 https://github.com/awslabs/amazon-bedrock-agentcore-samples/。

有关在 MCP 服务器上使用 OAuth 的信息,请参阅在运行时部署 MCP 服务器。 AgentCore

亚马逊 Bedrock AgentCore 运行时为托管代理提供了两种身份验证机制:

IAM SigV4 身份验证

与其他 AWS API 类似,默认的身份验证和授权机制无需额外配置即可自动运行。

X-Amzn-Bedrock-AgentCore-Runtime-User-Id 标题

如果您的解决方案要求托管代理代表最终用户检索 OAuth 令牌(使用授权码授予),则可以通过在X-Amzn-Bedrock-AgentCore-Runtime-User-Id请求中加入标头来指定用户标识符。此标头在内部使用该GetWorkloadAccessTokenForUserId路径。

注意

除了现有操作外X-Amzn-Bedrock-AgentCore-Runtime-User-Id header, InvokeAgentRuntime 使用调用还需要新bedrock-agentcore:InvokeAgentRuntimeForUser的 IAM bedrock-agentcore:InvokeAgentRuntime 操作:。

何时使用此标头与 JWT 持有令牌身份验证

此标头专为以下用例而设计:

  • 拥有客户管理的用户标识符的企业客户 — 维护自己的用户身份字符串并需要将其传递给 Ident AgentCore ity 进行凭据绑定的组织。

  • 开发和快速启动场景 — 尚未提供 IdP 代币且需要快速路径来测试用户范围内的凭证流的构建者。

    对于配置了身份提供商的生产部署,请改用 JWT 持有令牌身份验证。JWT 路径 (GetWorkloadAccessTokenForJWT) 验证代币的发行者、签名和到期时间,为用户的身份提供加密证明。标X-Amzn-Bedrock-AgentCore-Runtime-User-Id头路径不会根据经过身份验证的最终用户身份验证用户 ID,它依赖于调用工作负载传递正确的值,并依赖您的 IAM 策略来限制谁可以提供该值。

    X-Amzn-Bedrock-AgentCore-Runtime-User-Id Header 的安全最佳实践

    提示

    有关所有运行时安全建议的综合视图,请参阅 AgentCore 运行时安全最佳实践。

    由于 AgentCore 将标头值视为不透明的标识符,而不对照经过身份验证的身份进行验证,因此必须应用以下控制来维护安全边界:

  • 限制 IAM 权限 -只有可信委托人才有bedrock-agentcore:InvokeAgentRuntimeForUser权限。使用 IAM 资源条件将此权限范围限定为特定的运行时资源。不要通过管理策略或通配符资源声明对其进行广泛授权。

  • 从经过身份验证的主体派生用户 ID — 用户 ID 值应从经过身份验证的主体上下文(例如,IAM 呼叫者身份或用户令牌声明)中派生,而不是接受客户端提供的任意值。这可以防止经过身份验证的用户通过手动指定其他用户来冒充其他用户。user-id

  • 实施审计日志 -记录经过身份验证的 IAM 委托人(来自 SigV4 上下文)与传递的user-id值之间的关系。 AWS CloudTrail 用于监控包含runtimeUserId参数的InvokeAgentRuntime调用。

  • 在不可信的上下文中拒绝标头 — 对于不需要用户 ID 委托的运行时,在 IAM 策略中明确拒绝该bedrock-agentcore:InvokeAgentRuntimeForUser操作以防止标头被接受:

    { "Statement": [ { "Sid": "DenyUserIdDelegation", "Effect": "Deny", "Action": "bedrock-agentcore:InvokeAgentRuntimeForUser", "Resource": "arn:aws:bedrock-agentcore:REGION:ACCOUNT_ID:runtime/*" } ] }
JWT 持有者令牌认证

通过在代理创建期间提供授权器配置,您可以将代理运行时配置为接受 JWT 持有者令牌。

此配置包括:

  • 发现 URL-必须与 OpenID Connect 发现 URL ^.+/\.well-known/openid-configuration$ 的模式匹配的字符串

  • 允许的受众群体-允许的受众列表,将根据 JWT 代币中的澳元索赔进行验证

  • 允许的客户端-允许的客户端标识符列表,将根据 JWT 令牌中的 client_id 声明进行验证

  • 允许的范围-允许的范围列表,将根据 JWT 令牌中的范围声明进行验证。allowedScopes授权字段将配置为字符串列表。

  • 必填的自定义声明-必填声明列表,将根据传入 JWT 令牌中包含的声明名称和值进行验证。有关配置授权方的详细信息,请参阅配置入站 JWT 授权方

注意

AgentCore 运行时可以支持基于 IAM SigV4 或 JWT 不记名令牌的入站身份验证,但不能同时支持两者。您可以随时创建不同版本的 AgentCore Runtime,并将其配置为不同的入站授权类型。当您使用 Amazon Bedrock 创建运行时时 AgentCore,系统会使用身份服务自动为您的运行时创建工作负载身 AgentCore 份。

限制 IAM (SigV4) 对您的网关的入站调用

您可以在 AgentCore 运行时前使用 AgentCore 网关,使网关成为运行时的单一、受管控的入口点——为您提供基于策略的授权、Amazon Bedrock Guardrails、请求和响应拦截器以及统一的可观察性,所有这些都应用在代理自己的环境之外。有关完整原理以及如何进行此设置,请参阅使用 AgentCore 网关预置运行时间。

但是,这仅在调用者无法直接绕过网关到达运行时时才有用。如果您的运行时使用默认 IAM (SigV4) 入站授权,则可以限制对网关的调用,以便流量只能通过网关到达运行时。要实现这一点,请将基于资源的策略附加到运行时,限制对网关执行角色的调用。网关假定其服务角色来签署运行时请求,因此网关角色是调用运行时的主体。允许该角色,Deny并为所有其他主体添加明确的权限,这样即使使用基于身份的许可策略,其他身份也无法调用运行时。有关基于资源的运行时政策的更多信息,请参阅 Amazon Bedroc Resource-based k 的政策。 AgentCore

{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowOnlyGatewayRole", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::111122223333:role/MyGatewayExecutionRole" }, "Action": "bedrock-agentcore:InvokeAgentRuntime", "Resource": "arn:aws:bedrock-agentcore:us-west-2:111122223333:runtime/RUNTIME_ID" }, { "Sid": "DenyOtherPrincipals", "Effect": "Deny", "Principal": { "AWS": "*" }, "Action": "bedrock-agentcore:InvokeAgentRuntime", "Resource": "arn:aws:bedrock-agentcore:us-west-2:111122223333:runtime/RUNTIME_ID", "Condition": { "ArnNotEquals": { "aws:PrincipalArn": "arn:aws:iam::111122223333:role/MyGatewayExecutionRole" } } } ] }
提示

明确的策略Deny总是会覆盖同一个账户中的任何政策Allow,包括基于身份的政策。键入Deny开启aws:PrincipalArn可确保无论您的账户中存在哪些其他权限,只有网关的执行角色才能调用运行时。

重要

将运行时限制在网关的执行角色上,只有对谁可以担任该角色的控制一样有力。任何可以承担网关执行角色的委托人都可以像网关一样调用运行时。通过在网关执行角色的信任策略中添加aws:SourceArn和aws:SourceAccount条件来锁定角色,这样只有您的网关才能代入该角色。混乱的副手预防指南显示了适用于运行时执行角色的相同技术;在此应用相同的模式,但对网关执行角色和网关 ARN 的范围aws:SourceArn设置信任策略。

JWT 入站授权和 OAuth 出站访问示例

本指南引导您完成将代理运行时设置为使用 JWT 格式的 OAuth 兼容访问令牌调用的过程。样本代理将使用 AWS Cognito 访问令牌获得授权。稍后,您还将了解代理代码如何代表用户获取 Google 令牌以查看 Google 云端硬盘和提取内容。

你会学到什么

在本指南中,您将学习如何:

  • 设置 Cognito 用户池,添加用户,并为该用户获取持有者代币

  • 设置代理运行时以使用 Cognito 用户池进行授权

  • 设置代理代码以代表用户调用工具获取 OAuth 令牌

先决条件

开始之前,请确保您已具备以下条件:

  • 具有适当权限的 AWS 账户

  • 对 Python 编程的基本理解

  • 熟悉 Docker 容器(用于高级部署)

  • 成功设置具有运行时功能的基本代理

  • 最新的 AWS CLI 并jq已安装

  • 对 OAuth 授权的基本了解,主要是 JWT 持有者代币、索赔和各种拨款流程

第 1 步:创建代理项目

使用该agentcore create命令来设置一个空项目。在步骤 2 中创建 Cognito 资源后添加 JWT-authorized 代理。

agentcore create --project-name OAuthAgentProject --no-agent cd OAuthAgentProject

这会生成:

  • agentcore/agentcore.json 配置文件

  • agentcore/aws-targets.json部署目标文件

  • agentcore/cdk/基础设施项目

注意

将此终端保留在运行剩余OAuthAgentProject的 AgentCore CLI 命令中。

第 2 步:设置 AWS Cognito 用户池并添加用户

要设置 Cognito 用户池并创建用户,您将使用自动执行该过程的 shell 脚本。

有关更多信息,请参阅步骤 2:导入身份和身份验证模块。

设置 Cognito 用户池并创建用户

  • 使用以下内容创建名为 setup_cognito.sh 的文件:

    #!/bin/bash # Create User Pool and capture Pool ID directly export POOL_ID=$(aws cognito-idp create-user-pool \ --pool-name "MyUserPool" \ --policies '{"PasswordPolicy":{"MinimumLength":8}}' \ --region $REGION | jq -r '.UserPool.Id') # Create App Client and capture Client ID directly export CLIENT_ID=$(aws cognito-idp create-user-pool-client \ --user-pool-id $POOL_ID \ --client-name "MyClient" \ --no-generate-secret \ --explicit-auth-flows "ALLOW_USER_PASSWORD_AUTH" "ALLOW_REFRESH_TOKEN_AUTH" \ --region $REGION | jq -r '.UserPoolClient.ClientId') # Create User aws cognito-idp admin-create-user \ --user-pool-id $POOL_ID \ --username $USERNAME \ --region $REGION \ --message-action SUPPRESS > /dev/null # Set Permanent Password aws cognito-idp admin-set-user-password \ --user-pool-id $POOL_ID \ --username $USERNAME \ --password $PASSWORD \ --region $REGION \ --permanent > /dev/null # Authenticate User and capture Access Token export BEARER_TOKEN=$(aws cognito-idp initiate-auth \ --client-id "$CLIENT_ID" \ --auth-flow USER_PASSWORD_AUTH \ --auth-parameters USERNAME=$USERNAME,PASSWORD=$PASSWORD \ --region $REGION | jq -r '.AuthenticationResult.AccessToken') # Output the required values echo "Pool id: $POOL_ID" echo "Discovery URL: https://cognito-idp.$REGION.amazonaws.com/$POOL_ID/.well-known/openid-configuration" echo "Client ID: $CLIENT_ID" echo "Bearer Token: $BEARER_TOKEN"

    打开终端窗口并设置以下环境变量:

    • REGION— 您要使用的 AWS 区域

    • USERNAME— 新用户的用户名

    • PASSWORD— 新用户的密码

      export REGION=us-east-1 # Set your desired Region export USERNAME="user-name" export PASSWORD="password"

      在终端窗口中,运行脚本:

      source setup_cognito.sh

      记下脚本的输出。在接下来的步骤中,您将需要这些值。

此脚本创建 Cognito 用户池、用户池客户端、添加用户并为用户生成持有者令牌。默认情况下,该令牌的有效期为 60 分钟。

第 3 步(可选):使用 AgentCore 网关作为运行前端

您可以在 AgentCore 运行时前使用 AgentCore 网关,使网关成为运行时的单一、受管控的入口点——为您提供基于策略的授权、Amazon Bedrock Guardrails、请求和响应拦截器以及统一的可观察性,所有这些都应用在代理自己的环境之外。有关完整原理以及如何进行此设置,请参阅使用 AgentCore 网关预置运行时间。

如果您想提前部署此运行时,请立即创建网关,然后在下一步部署运行时。部署后,您需要将运行时添加为网关目标。

为确保调用者无法绕过网关,请将运行时间限制为仅接受来自该网关的调用。allowedWorkloadConfiguration按允许的方法使用WorkloadConfiguration:限制对网关的调用。C AgentCore LI 不配置此字段。使用 AgentCore 控制平面 API。

第 4 步:部署您的代理

重要

从 2025 年 10 月 13 日起,Amazon Bedrock AgentCore 使用 Service-Linked 角色 (SLR) 来获得工作负载身份权限,而不是要求为新代理手动配置 IAM 策略。

Service-Linked 角色详情:

  • 名称:AWSServiceRoleForBedrockAgentCoreRuntimeIdentity

  • 服务负责人:runtime-identity.bedrock-agentcore.amazonaws.com

  • 目的:管理工作负载身份访问令牌和 OAuth 凭证

确保您用于调用 AgentCore 控制 API 的角色有权创建该 Service-Linked 角色:

{ "Sid": "CreateBedrockAgentCoreIdentityServiceLinkedRolePermissions", "Effect": "Allow", "Action": "iam:CreateServiceLinkedRole", "Resource": "arn:aws:iam::*:role/aws-service-role/runtime-identity.bedrock-agentcore.amazonaws.com/AWSServiceRoleForBedrockAgentCoreRuntimeIdentity", "Condition": { "StringEquals": { "iam:AWSServiceName": "runtime-identity.bedrock-agentcore.amazonaws.com" } } }

好处:该 Service-Linked 角色可自动为工作负载身份访问提供必要的权限,无需手动配置策略。

有关服务相关角色的详细信息,请参阅身份服务相关角色。

现在,您将使用您创建的 Cognito 用户池部署具有 JWT 授权的代理。您将需要使用授权者配置创建代理。下表列出了各种授权者配置参数以及我们如何使用它们来验证传入的令牌。

授权器配置 在解码后的代币中申领 注意

发现网址 → 发行人

iss

发现网址应指向发行者网址。这应该与解码后的令牌中的 iss 声明相匹配。

允许的客户

client_id

令牌中的 client_id 应与授权者中指定的允许客户端之一相匹配

允许的观众

aud

代币的澳元申领值中的一个值应与授权者中指定的允许受众之一相匹配

允许的 WorkloadConfiguration

internal

可选。启动时,用于仅允许您的 AgentCore 网关调用运行时。请参阅限制对您的网关的调用。

如果同时提供了 client_id 和 aud,则代理运行时授权者将对两者进行验证。

允许WorkloadConfiguration:限制对您的网关的调用

上的allowedWorkloadConfiguration字段customJWTAuthorizer限制了允许请求身份链中的哪些工作负载调用运行时。为您的网关设置允许的工作负载,以便运行时仅在其身份链包含该网关时才接受请求——这就是 OAuth (JWT) 运行时强制流量仅通过您在步骤 3 中设置的网关到达的方式。

您可以使用以下任一字段提供允许的工作负载。您可以指定其中一个或两个——如果请求的身份链与任一字段中的条目相匹配,则该请求将被接受,因此您无需同时提供这两个信息。

  • 托管环境 -允许其工作负载调用目标的主机环境列表。每个条目都是一个带有arn. 启动时,唯一支持的主机环境是 AgentCore Gateway,因此每个托管环境都arn必须是 AgentCore 网关 ARN。

  • WorkloadIdentities — 允许调用目标的工作负载身份名称列表。工作负载标识名称不是 ARN。这是网关工作负载身份 ARN 的最后一部分,您可以在GetGateway响应workloadIdentityDetails字段中找到。例如,如果workloadIdentityDetails.workloadIdentityArn是arn:aws:bedrock-agentcore:us-east-1:111122223333:workload-identity-directory/default/workload-identity/my-gateway-workload-identity,则工作负载标识名称为my-gateway-workload-identity。

以下授权方配置通过其 ARN 限制对特定 AgentCore 网关的调用。hostingEnvironments单独指定是允许网关的最简单方法:

{ "authorizerConfiguration": { "customJWTAuthorizer": { "discoveryUrl": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_example/.well-known/openid-configuration", "allowedClients": ["your-client-id"], "allowedWorkloadConfiguration": { "hostingEnvironments": [ { "arn": "arn:aws:bedrock-agentcore:us-east-1:111122223333:gateway/my-gateway-id" } ] } } } }

或者,您可以通过网关的工作负载标识名称来识别网关,也可以同时指定这两个字段。当两者都存在时,如果请求与任一字段中的条目相匹配,则允许该请求。以下allowedWorkloadConfiguration代码段允许使用两个不同的网关——一个由其 ARN 标识,另一个由其工作负载标识名称标识:

"allowedWorkloadConfiguration": { "hostingEnvironments": [ { "arn": "arn:aws:bedrock-agentcore:us-east-1:111122223333:gateway/my-gateway-1-id" } ], "workloadIdentities": [ "my-gateway-2-workload-identity" ] }
注意

启动时,allowedWorkloadConfiguration仅支持 AgentCore 运行时目标,允许的工作负载为 AgentCore 网关。

创建和部署代理运行时

准备好授权器配置后,创建和部署代理运行时。以下示例说明如何使用 AgentCore CLI 或 Python AWS 开发工具包 (Boto3) 来执行此操作。记下输出中的代理运行时 ARN ——在下一步中,您需要它来调用代理。

例
AgentCore CLI

配置和部署您的代理

  1. 将代理添加到您在步骤 1 中创建的项目中。该命令配置 Cognito 发现 URL、客户端 ID 和Authorization请求标头许可名单:

    agentcore add agent \ --name OAuthAgent \ --language Python \ --framework Strands \ --model-provider Bedrock \ --memory none \ --authorizer-type CUSTOM_JWT \ --discovery-url "https://cognito-idp.$REGION.amazonaws.com/$POOL_ID/.well-known/openid-configuration" \ --allowed-clients "$CLIENT_ID" \ --request-header-allowlist Authorization
  2. 部署您的代理:

    agentcore deploy
  3. 记下输出中的代理运行时 ARN。在下一步你将需要这个。

Python
  1. import boto3 # Create the client client = boto3.client('bedrock-agentcore-control', region_name="us-east-1") # Call the CreateAgentRuntime operation response = client.create_agent_runtime( agentRuntimeName='HelloAgent', agentRuntimeArtifact={ 'containerConfiguration': { 'containerUri': '111122223333.dkr.ecr.us-east-1.amazonaws.com/my-agent:latest' } }, authorizerConfiguration={ "customJWTAuthorizer": { "discoveryUrl": 'COGNITO_DISCOVERY_URL', "allowedClients": ['COGNITO_CLIENT_ID'] } }, networkConfiguration={"networkMode":"PUBLIC"}, roleArn='arn:aws:iam::111122223333:role/AgentRuntimeRole', lifecycleConfiguration={ 'idleRuntimeSessionTimeout': 300, # 5 min, configurable 'maxLifetime': 1800 # 30 minutes, configurable }, )
注意

AgentCore CLI 示例配置了 JWT 授权,但它没有配置。allowedWorkloadConfiguration如果您在运行时使用网关,请使用 AgentCore 控制平面 API 来添加该字段。

第 5 步:使用不记名代币调用您的代理

现在您的代理已通过 JWT 授权部署,您可以使用持有者令牌调用它。

注意

如果您在步骤 3 中使用网关作为运行时前端,请在调用之前将已部署的运行时添加为网关目标(请参阅AgentCore 运行时目标),然后通过以下示例中显示的网关端点而不是运行时终端节点进行调用。

重要

对现有用户很重要:2025 年 10 月 13 日之前创建的代理将继续使用代理执行角色获取身份权限,并要求将前面的策略附加到代理的执行角色。

新代理:对于 2025 年 10 月 13 日当天或之后创建的代理,不需要此政策,因为权限由 Service-Linked 角色自动处理。

{ "Sid": "GetAgentAccessToken", "Effect": "Allow", "Action": [ "bedrock-agentcore:GetWorkloadAccessToken", "bedrock-agentcore:GetWorkloadAccessTokenForJWT", "bedrock-agentcore:GetWorkloadAccessTokenForUserId" ], # point to the workload identity for the runtime; the workload identity can be found in # the GetAgentRuntime response and has your agent name in it. "Resource": [ "arn:aws:bedrock-agentcore:region:account-id:workload-identity-directory/default", "arn:aws:bedrock-agentcore:region:account-id:workload-identity-directory/default/workload-identity/agentname-*" ] }

调用代理

为您使用亚马逊 Cognito 创建的用户获取不记名代币。

# use the password and other details used when you created the cognito user export TOKEN=$(aws cognito-idp initiate-auth \ --client-id "$CLIENT_ID" \ --auth-flow USER_PASSWORD_AUTH \ --auth-parameters USERNAME='testuser',PASSWORD='PASSWORD' \ --region us-east-1 | jq -r '.AuthenticationResult.AccessToken')

按照以下其余说明继续调用代理。

使用 OAuth 调用代理。

例
Use cURL
  1. // Invoke with OAuth token export PAYLOAD='{"prompt": "hello what is 1+1?"}' export BEDROCK_AGENT_CORE_ENDPOINT_URL="https://bedrock-agentcore.us-east-1.amazonaws.com" # If you fronted the runtime with a gateway (Step 3), the core endpoint URL is now your gateway URL # export BEDROCK_AGENT_CORE_ENDPOINT_URL="https://${GATEWAY_ID}.gateway.bedrock-agentcore.us-east-1.amazonaws.com/${TARGET_NAME}" export INVOKE_URL="${BEDROCK_AGENT_CORE_ENDPOINT_URL}/runtimes/${ESCAPED_AGENT_ARN}/invocations?qualifier=DEFAULT" # If you fronted the runtime with a gateway (Step 3), the preceding URL works but there is also a simpler alternative: # export INVOKE_URL="${BEDROCK_AGENT_CORE_ENDPOINT_URL}/invocations" curl -v -X POST "${INVOKE_URL}" \ -H "Authorization: Bearer ${TOKEN}" \ -H "X-Amzn-Trace-Id: your-trace-id" \ -H "Content-Type: application/json" \ -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: your-session-id" \ -d ${PAYLOAD}
Use Python
  1. 由于 boto3 不支持使用不记名令牌进行调用,因此你需要使用像 Python 中的请求库一样的 HTTP 客户端。

    使用持有者代币调用您的代理

  2. 使用以下内容创建名invoke_agent.py为 Python 脚本:

    import requests import urllib.parse import json import os # Configuration Constants REGION_NAME = "AWS_REGION" # === Agent Invocation Demo === invoke_agent_arn = "YOUR_AGENT_ARN_HERE" auth_token = os.environ.get('TOKEN') print(f"Using Agent ARN from environment: {invoke_agent_arn}") # URL encode the agent ARN escaped_agent_arn = urllib.parse.quote(invoke_agent_arn, safe='') # Construct the URL — invoke the runtime directly url = f"https://bedrock-agentcore.{REGION_NAME}.amazonaws.com/runtimes/{escaped_agent_arn}/invocations?qualifier=DEFAULT" # If you are fronting the runtime with a gateway (see Step 3), invoke through # the gateway target instead (replace GATEWAY_ID and my-target): # url = f"https://GATEWAY_ID.gateway.bedrock-agentcore.{REGION_NAME}.amazonaws.com/my-target/invocations" # Set up headers headers = { "Authorization": f"Bearer {auth_token}", "X-Amzn-Trace-Id": "your-trace-id", "Content-Type": "application/json", "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id": "testsession123" } # Enable verbose logging for requests import logging logging.basicConfig(level=logging.DEBUG) logging.getLogger("urllib3.connectionpool").setLevel(logging.DEBUG) invoke_response = requests.post( url, headers=headers, data=json.dumps({"prompt": "Hello what is 1+1?"}) ) # Print response in a safe manner print(f"Status Code: {invoke_response.status_code}") print(f"Response Headers: {dict(invoke_response.headers)}") # Handle response based on status code if invoke_response.status_code == 200: response_data = invoke_response.json() print("Response JSON:") print(json.dumps(response_data, indent=2)) elif invoke_response.status_code >= 400: print(f"Error Response ({invoke_response.status_code}):") error_data = invoke_response.json() print(json.dumps(error_data, indent=2)) else: print(f"Unexpected status code: {invoke_response.status_code}") print("Response text:") print(invoke_response.text[:500])
  3. AWS_REGION替换为步骤 3 中您正在使用的 AWS 区域。

  4. YOUR_AGENT_ARN_HERE使用步骤 3 中的实际代理运行时 ARN 替换。

  5. 运行脚本:

    python invoke_agent.py

OAuth 错误响应

OAuth-configured 代理遵循 RFC 6749 (OAuth 2.0) 身份验证标准。缺少身份验证时,该服务会返回带有 WWW-Authenticate 标头的 401 未经授权的响应(根据 RFC 7235),使客户端能够通过 API 发现授权服务器端点。 GetRuntimeProtectedResourceMetadata

401 未经授权-缺少身份验证

当授权标头中未提供不记名令牌时,响应为:

HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer resource_metadata="https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{ESCAPED_ARN}/invocations/.well-known/oauth-protected-resource?qualifier={QUALIFIER}"

WWW-Authenticate 标题中的 resource_metadata URL 指向受保护资源元数据 (PRM) API。PRM API 使客户端能够发现哪些授权服务器保护了该代理及其 OAuth 端点 URL。

注意

在使用发现的端点client_id之前,您必须在 Cognito 中预先注册 OAuth 客户端(通过 AWS 控制台或 CLI)以获取。亚马逊 Cognito 不支持动态客户端注册 (RFC 7591)。

第 6 步:设置您的代理以使用 OAuth 访问工具

在本节中,您将学习如何将代理代码与 AgentCore 凭据提供者连接起来,以便使用 OAuth2 身份验证安全访问外部资源。

以下示例演示了在 Agent Runtime 中运行的代理如何请求用户的 OAuth 同意,从而使他们能够使用自己的 Google 帐号进行身份验证并授权代理访问其 Google 云端硬盘内容。

有关设置身份的更多信息,请参阅 AgentCore 身份入门。

步骤 6.1:设置凭证提供商

要设置 Google 凭证提供商,您需要:

  1. 向 Google 注册您的应用程序以获取客户端 ID 和客户端密钥

  2. 使用 CLI 创建 OAuth 凭证提供商。 AWS 将your-client-id和your-client-secret替换为您的实际的 Google OAuth2 客户端 ID 和客户端密钥:

    OAUTH2_CREDENTIAL_PROVIDER_RESPONSE=$(aws bedrock-agentcore-control create-oauth2-credential-provider \ --name "google-provider" \ --credential-provider-vendor "GoogleOauth2" \ --oauth2-provider-config-input '{ "googleOauth2ProviderConfig": { "clientId": "your-client-id", "clientSecret": "your-client-secret" } }' \ --output json) OAUTH2_CALLBACK_URL=$(echo $OAUTH2_CREDENTIAL_PROVIDER_RESPONSE | jq -r '.callbackUrl') echo "OAuth2 Callback URL: $OAUTH2_CALLBACK_URL"
    注意

    callbackUrl从CreateOauth2CredentialProvider响应中获取并将该 URI 添加到 Google 应用程序的重定向 URI 列表中。回调 URL 应如下所示:https://bedrock-agentcore.us-east-1.amazonaws.com/identities/oauth2/callback/********-******-******-************************

确保您的调用角色具有访问凭证提供商的必要权限。

步骤 6.2:允许代理读取 Google 云端硬盘内容

创建带有代理核心 SDK 注释的工具,如以下示例所示,以自动启动三步 OAuth 流程。当您的代理调用此工具时,系统会提示用户在浏览器中打开授权网址,并同意代理访问他们的 Google 云端硬盘。

import asyncio from bedrock_agentcore.identity.auth import requires_access_token, requires_api_key # This annotation helps agent developer to obtain access tokens from external applications @requires_access_token( provider_name="google-provider", scopes=["https://www.googleapis.com/auth/drive.metadata.readonly"], # Google OAuth2 scopes auth_flow="USER_FEDERATION", # 3LO flow on_auth_url=lambda x: print("Copy and paste this authorization url to your browser: ", x), # prints authorization URL to console force_authentication=True, callback_url='insert_oauth2_callback_url_for_session_binding' ) async def read_from_google_drive(*, access_token: str): print(access_token) #You can see the access_token # Make API calls... main(access_token) asyncio.run(read_from_google_drive(access_token=""))

幕后会发生什么

当此代码运行时,会发生以下过程:

  1. 代理运行时根据配置的授权方对入站令牌进行授权。

  2. 代理运行时通过 bedrock-agentcore:GetWorkloadAccessTokenForJWT API 将此令牌交换为工作负载访问令牌,并通过有效负载标头将其传递给您的代理代码WorkloadAccessToken。

  3. 在工具调用期间,您的代理使用此工作负载访问令牌调用令牌库 API bedrock-agentcore:GetResourceOauth2Token 并生成 3LO 身份验证网址。

  4. 您的代理将此 URL 发送到on_auth_url方法中指定的客户端应用程序。

  5. 客户端应用程序将此网址提供给用户,用户同意代理访问其 Google 云端硬盘。

  6. AgentCore 身份服务会安全地接收和缓存 Google 访问令牌直至其过期,这样,用户的后续请求就可以使用该令牌,而无需用户对每个请求表示同意。

注意

AgentCore 身份服务使用代理工作负载身份和用户 ID(来自入站 JWT AgentCore 令牌,例如 AWS Cognito 令牌)作为绑定密钥将 Google 访问令牌存储在令牌库中,从而消除了在 Google 令牌到期之前重复的同意请求。

第 7 步:(可选)将 JWT 令牌传播到运行时 AgentCore

或者,您可以将授权标头传递给 AgentCore Runtime 以提取索赔。这可以通过使用请求标头允许列表配置来完成。有关更多信息,请参阅 RequestHeaderConfiguration。

第 7.1 步:修改代理代码以读取标题

在此步骤中,您将更改代理代码,以便可以使用 PyJWT 库对 JWT 令牌进行解码和提取索赔。

Python 依赖

将 PyJWT 添加到生成的代理中:pyproject.toml

cd app/OAuthAgent uv add PyJWT cd ../..

更新您的代理代码

按以下代码app/OAuthAgent/main.py所示进行修改。您可以在此处跳过验证令牌签名,因为 AgentCore Runtime 已经在入站授权期间验证了令牌。

import jwt import json .... @app.entrypoint def invoke(payload, context): auth_header = context.request_headers.get('Authorization') if not auth_header: return None # Remove "Bearer " prefix if present token = auth_header.replace('Bearer ', '') if auth_header.startswith('Bearer ') else auth_header try: # Skip signature validation as agent runtime has validated the token already. claims = jwt.decode(token, options={"verify_signature": False}) app.logger.info("Claims: %s", json.dumps(claims)) except jwt.InvalidTokenError as e: app.logger.exception("Invalid JWT token: %s", e) .....

步骤 7.2:部署更新的代理

步骤 4 中的agentcore add agent命令已经配置了Authorization请求标头允许列表。部署代码更新:

agentcore deploy

步骤 7.3:调用您的代理

使用 OAuth 调用您的代理,您应该会在代理日志中的日志中 CloudWatch 看到索赔。

问题排查

如何调试与令牌相关的问题

如果您遇到令牌身份验证问题,则可以对令牌进行解码以检查其内容:

echo "$TOKEN" | cut -d '.' -f2 | tr '_-' '/+' | awk '{ l=4 - length($0)%4; if (l<4) printf "%s", $0; for (i=0; i<l; i++) printf "="; print "" }' | base64 -D | jq

这将输出代币的有效载荷,其外观类似于:

{ "sub": "subid", "iss": "https://cognito-idp.us-east-1.amazonaws.com/userpoolid", "client_id": "clientid", "origin_jti": "originjti", "event_id": "eventid", "token_use": "access", "scope": "aws.cognito.signin.user.admin", "auth_time": 1752275688, "exp": 1752279288, "iat": 1752275688, "jti": "jti", "username": "username" }

对令牌问题进行故障排除时,请检查以下内容:

  • 代理授权方中的发现网址指向的发行者网址应与令牌中的发行者声明相匹配。执行以下操作以确认它们匹配:

    • 选择您在创建代理时在授权者配置中提供的发现 URL,例如:https://cognito-idp.us-east-1.amazonaws.com/us-east-1_nnnnnnnnn/.well-known/openid-configuration

      • 查看发行人网址-"issuer": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_12345566". 这应该与令牌中的 iss 声明值相匹配。

  • client_id令牌中的声明必须与授权方 allowedClients 条目中的一个(如果提供)相匹配

    • 记下您在创建代理时提供的客户端 ID

    • 确认这与解码后的令牌中的 client_id 声明相匹配

  • aud令牌中的声明必须与授权方allowedAudience条目之一相匹配(如果提供)

    • 记下您在创建代理时提供的受众列表

    • 确认这与解码后的aud令牌中的声明相匹配

  • 令牌的有效期仅为几分钟(默认的亚马逊 Cognito 到期时间为 60 分钟)。根据需要获取新代币。