

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

# 构建您的第一个经过身份验证的代理
<a name="identity-getting-started-cognito"></a>

本入门教程将引导您使用 Amazon Bedrock Identity 从头开始构建经过 AgentCore 身份验证的完整代理，并将帮助您开始在代理应用程序中实现身份功能。您将学习如何设置开发环境、使用 Cognito 创建身份验证基础架构、将代理部署到 AgentCore Runtime 以及测试完整的身份验证工作流程。

在本教程结束时，您将拥有一个完全部署的代理，该代理可以通过 OAuth2 流程对用户进行身份验证，安全地获取访问令牌，并演示完整的身份管理生命周期。您的代理将使用适当的 IAM 权限在 AgentCore Runtime 上运行，从而创建一个测试实验室环境，您可以在其中演示和测试集成能力。

**Topics**
+ [先决条件](#identity-quick-start-prerequisites)
+ [第 1 步：创建 Cognito 用户池（可选）](#identity-quick-start-cognito)
+ [第 2 步：创建凭证提供商](#identity-quick-start-credential-provider)
+ [第 2.5 步：将回调 URL 添加到 OAuth 2.0 授权服务器](#identity-update-credential-provider)
+ [第 3 步：创建启动 OAuth 2.0 流程的示例代理](#identity-quick-start-agent)
+ [步骤 4：将代理部署到 AgentCore 运行时](#identity-quick-start-deploy)
+ [第 5 步：调用代理](#identity-quick-start-invoke)
+ [清理](#identity-quick-start-cleanup)
+ [安全最佳实践](#identity-quick-start-security)

## 先决条件
<a name="identity-quick-start-prerequisites"></a>

在开始之前，请确保您满足以下条件：
+ 具有适当权限的 Amazon 账户
+ 已安装 Python 3.10\+
+  [https://docs.astral.sh/uv/getting-started/installation/](https://docs.astral.sh/uv/getting-started/installation/)已安装紫外线
+ 最新的 Amazon CLI 并`jq`已安装
+ Node.js 已安装 20 个以上（用于 AgentCore CLI）
+  Amazon 证书和区域已配置 (`aws configure`)

本教程要求您拥有 OAuth 2.0 授权服务器。如果您没有，步骤 1 将使用 Amazon Cognito 用户池为您创建一个用户池。如果您的 OAuth 2.0 授权服务器配置了客户端 ID、客户端密钥和用户，则可以继续执行步骤 2。该授权服务器将充当资源凭证提供者，代表向代理授予出站 OAuth 2.0 访问令牌的权限。

### 安装 SDK 和依赖项
<a name="identity-quick-start-install"></a>

为本指南创建一个文件夹，创建 Python 虚拟环境，然后安装 AgentCore SDK 和 Amazon Python 开发工具包 (boto3)。

```
mkdir agentcore-identity-quickstart
cd agentcore-identity-quickstart
python3 -m venv .venv
source .venv/bin/activate
pip install bedrock-agentcore boto3 strands-agents pyjwt
```

## 第 1 步：创建 Cognito 用户池（可选）
<a name="identity-quick-start-cognito"></a>

本教程需要 OAuth 2.0 授权服务器。如果您没有可供测试的，或者您想将测试与授权服务器分开，则此脚本将使用您的 Amazon 证书设置一个 Amazon Cognito 实例供您用作授权服务器。该脚本将创建：
+ Cognito 用户池
+ OAuth 2.0 客户端，以及该用户池的客户端密钥
+ 该 Cognito 用户池中的测试用户和密码

删除 Cognito 用户池 AgentCoreIdentityQuickStartPool 也会删除关联的 client\_id 和用户。

您可以选择将此脚本另存为 create\_cognito.sh 并从命令行执行，也可以将脚本粘贴到命令行中。

```
#!/bin/bash

REGION=$(aws configure get region)

# Create user pool
USER_POOL_ID=$(aws cognito-idp create-user-pool \
  --pool-name AgentCoreIdentityQuickStartPool \
  --query 'UserPool.Id' \
  --no-cli-pager \
  --output text)

# Create user pool domain
DOMAIN_NAME="agentcore-quickstart-$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 5)"
aws cognito-idp create-user-pool-domain \
  --domain $DOMAIN_NAME \
  --no-cli-pager \
  --user-pool-id $USER_POOL_ID > /dev/null

# Create user pool client with secret and hosted UI settings
CLIENT_RESPONSE=$(aws cognito-idp create-user-pool-client \
  --user-pool-id $USER_POOL_ID \
  --client-name AgentCoreQuickStart \
  --generate-secret \
  --allowed-o-auth-flows "code" \
  --allowed-o-auth-scopes "openid" "profile" "email" \
  --allowed-o-auth-flows-user-pool-client \
  --supported-identity-providers "COGNITO" \
  --query 'UserPoolClient.{ClientId:ClientId,ClientSecret:ClientSecret}' \
  --output json)

CLIENT_ID=$(echo $CLIENT_RESPONSE | jq -r '.ClientId')
CLIENT_SECRET=$(echo $CLIENT_RESPONSE | jq -r '.ClientSecret')

# Generate random username and password
USERNAME="AgentCoreTestUser$(printf "%04d" $((RANDOM % 10000)))"
PASSWORD="$(LC_ALL=C tr -dc 'A-Za-z0-9!@#$%^&*()_+-=[]{}|;:,.<>?' < /dev/urandom | head -c 16)$(LC_ALL=C tr -dc '0-9' < /dev/urandom | head -c 1)"

# Create user with permanent password
aws cognito-idp admin-create-user \
  --user-pool-id $USER_POOL_ID \
  --username $USERNAME \
  --output text > /dev/null

aws cognito-idp admin-set-user-password \
  --user-pool-id $USER_POOL_ID \
  --username $USERNAME \
  --password $PASSWORD \
  --output text > /dev/null \
  --permanent

# Get region

ISSUER_URL="https://cognito-idp.$REGION.amazonaws.com/$USER_POOL_ID/.well-known/openid-configuration"
HOSTED_UI_URL="https://$DOMAIN_NAME.auth.$REGION.amazoncognito.com"

# Output results
echo "User Pool ID: $USER_POOL_ID"
echo "Client ID: $CLIENT_ID"
echo "Client Secret: $CLIENT_SECRET"
echo "Issuer URL: $ISSUER_URL"
echo "Hosted UI URL: $HOSTED_UI_URL"
echo "Test User: $USERNAME"
echo "Test Password: $PASSWORD"

echo ""
echo "# Copy and paste these exports to set environment variables for later use:"
echo "export USER_POOL_ID='$USER_POOL_ID'"
echo "export CLIENT_ID='$CLIENT_ID'"
echo "export CLIENT_SECRET='$CLIENT_SECRET'"
echo "export ISSUER_URL='$ISSUER_URL'"
echo "export HOSTED_UI_URL='$HOSTED_UI_URL'"
echo "export COGNITO_USERNAME='$USERNAME'"
echo "export COGNITO_PASSWORD='$PASSWORD'"
```

## 第 2 步：创建凭证提供商
<a name="identity-quick-start-credential-provider"></a>

凭证提供商是您的代理访问外部服务的方式。创建凭证提供商，并使用授权服务器的 OAuth 2.0 客户端对其进行配置。

如果您使用自己的授权服务器，请设置环境变量 `ISSUER_URL``CLIENT_ID`，并`CLIENT_SECRET`使用授权服务器中的相应值。如果您使用前面的脚本使用 Cognito 为您创建授权服务器，请将输出中的 EXPORT 语句复制到终端以设置环境变量。

您的代理代码将使用该凭证提供商来获取访问令牌，以代表您的用户行事。

**Example**  

1. 如果您有 AgentCore CLI 项目，则可以使用 CLI 添加凭证提供商。CLI 将在部署期间创建提供商。

   ```
   agentcore add credential \
     --name AgentCoreIdentityQuickStartProvider \
     --type oauth \
     --discovery-url "$ISSUER_URL" \
     --client-id "$CLIENT_ID" \
     --client-secret "$CLIENT_SECRET"
   ```

   当您在步骤 4 `agentcore deploy` 中运行时，将创建凭证提供商。记下部署输出中的回调 URL。

1. 

   ```
   #!/bin/bash
   # please note the expected ISSUER_URL format for Bedrock AgentCore is the full url, including .well-known/openid-configuration
   OAUTH2_CREDENTIAL_PROVIDER_RESPONSE=$(aws bedrock-agentcore-control create-oauth2-credential-provider \
     --name "AgentCoreIdentityQuickStartProvider" \
     --credential-provider-vendor "CustomOauth2" \
     --oauth2-provider-config-input '{
       "customOauth2ProviderConfig": {
         "oauthDiscovery": {
           "discoveryUrl": "'$ISSUER_URL'"
         },
         "clientId": "'$CLIENT_ID'",
         "clientSecret": "'$CLIENT_SECRET'"
       }
     }' \
     --output json)
   
   OAUTH2_CALLBACK_URL=$(echo $OAUTH2_CREDENTIAL_PROVIDER_RESPONSE | jq -r '.callbackUrl')
   
   echo "OAuth2 Callback URL: $OAUTH2_CALLBACK_URL"
   ```

## 第 2.5 步：将回调 URL 添加到 OAuth 2.0 授权服务器
<a name="identity-update-credential-provider"></a>

为防止未经授权的重定向，请将从 OAuth 2.0 授权服务器检索到[CreateOauth2CredentialProvider](https://docs.amazonaws.cn/bedrock-agentcore-control/latest/APIReference/API_CreateOauth2CredentialProvider.html)的回调 URL [ GetOauth2CredentialProvider ](https://docs.amazonaws.cn/bedrock-agentcore-control/latest/APIReference/API_GetOauth2CredentialProvider.html) 添加到您的 OAuth 2.0 授权服务器中。

如果您使用前面的脚本使用 Cognito 创建授权服务器，请将输出中的 EXPORT 语句复制到您的终端以设置环境变量，并使用 OAuth2 凭据提供商回调 URL 更新 Cognito 用户池客户端。

```
#!/bin/bash
aws cognito-idp update-user-pool-client \
    --user-pool-id $USER_POOL_ID \
    --client-id $CLIENT_ID \
    --client-name AgentCoreQuickStart \
    --allowed-o-auth-flows "code" \
    --allowed-o-auth-scopes "openid" "profile" "email" \
    --allowed-o-auth-flows-user-pool-client \
    --supported-identity-providers "COGNITO" \
    --callback-urls "$OAUTH2_CALLBACK_URL"
```

## 第 3 步：创建启动 OAuth 2.0 流程的示例代理
<a name="identity-quick-start-agent"></a>

在此步骤中，我们将创建一个代理，该代理启动 OAuth 2.0 授权流程，以获取代币以用户的名义行事。为简单起见，代理不会代表用户实际拨打外部服务，但会向我们证明其已获得同意代表我们的测试用户行事。

### 代理代码
<a name="identity-quick-start-agent-code"></a>

创建一个名为`agentcoreidentityquickstart.py`的文件并保存此代码。

```
"""
AgentCore Identity Outbound Token Agent

This agent demonstrates the USER_FEDERATION OAuth 2.0 flow.

It handles the OAuth 2.0 user consent flow and inspects the resulting OAuth 2.0 access token.
"""

from bedrock_agentcore.runtime import BedrockAgentCoreApp
from bedrock_agentcore.identity import requires_access_token
import asyncio
import jwt
import logging

app = BedrockAgentCoreApp()

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def decode_jwt(token):
    try:
        decoded = jwt.decode(token, options={"verify_signature": False})
        return decoded
    except Exception as e:
        return {"error": f"Error decoding JWT: {str(e)}"}

class StreamingQueue:
    def __init__(self):
        self.finished = False
        self.queue = asyncio.Queue()

    async def put(self, item):
        await self.queue.put(item)

    async def finish(self):
        self.finished = True
        await self.queue.put(None)

    async def stream(self):
        while True:
            item = await self.queue.get()
            if item is None and self.finished:
                break
            yield item

queue = StreamingQueue()

async def handle_auth_url(url):
    await queue.put(f"Authorization URL, please copy to your preferred browser: {url}")

@requires_access_token(
    provider_name="AgentCoreIdentityQuickStartProvider",
    scopes=["openid"],
    auth_flow="USER_FEDERATION",
    on_auth_url=handle_auth_url, # streams authorization URL to client
    force_authentication=True,
    callback_url='insert_oauth2_callback_url_for_session_binding',
)
async def introspect_with_decorator(*, access_token: str):
    """Introspect token using decorator"""
    logger.info("Inside introspect_with_decorator - decorator succeeded")
    await queue.put({
        "message": "Successfully received an access token to act on behalf of your user!",
        "token_claims": decode_jwt(access_token),
        "token_length": len(access_token),
        "token_preview": f"{access_token[:50]}...{access_token[-10:]}"
    })
    await queue.finish()

@app.entrypoint
async def agent_invocation(payload, context):
    """Handler that uses only the decorator approach"""
    logger.info("Agent invocation started")

    # Start the agent task and immediately begin streaming
    task = asyncio.create_task(introspect_with_decorator())

    # Stream items as they come in
    async for item in queue.stream():
        yield item

    # Wait for task completion
    await task

if __name__ == "__main__":
    app.run()
```

**注意**  
有关处理[会话绑定的本地回调服务器实现示例](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/oauth2-authorization-url-session-binding.html)，请参阅 [ oauth2\_callback\_server.py ](https://github.com/awslabs/amazon-bedrock-agentcore-samples/blob/main/01-features/05-authenticate-and-authorize/02-outbound-auth/02-outbound-auth-3lo/oauth2_callback_server.py) 

## 步骤 4：将代理部署到 AgentCore 运行时
<a name="identity-quick-start-deploy"></a>

我们将在 AgentCore Runtime 上托管这个代理。我们可以使用 AgentCore CLI 轻松完成此操作。

在您的终端上安装 AgentCore CLI 并创建 Python Strands 代理项目。显式选项创建了基于代码的代理而不是工具：

```
npm install -g @aws/agentcore
agentcore create --name IdentityQuickstart --language Python --framework Strands \
  --model-provider Bedrock --memory none
```

将代理脚本复制到项目的代理目录中，替换默认代理：

```
cp agentcoreidentityquickstart.py IdentityQuickstart/app/IdentityQuickstart/main.py
```

将 JWT 依赖项添加到生成的项目中：

```
cd IdentityQuickstart/app/IdentityQuickstart
uv add pyjwt
cd ../..
```

然后部署你的项目：

```
agentcore deploy
```

CLI 合成 Amazon CDK 堆栈并将您的代理部署到运行时。 AgentCore 这大约需要 2-3 分钟。

### 更新代理的 IAM 政策，以便能够访问代币库和客户端密钥
<a name="identity-quick-start-iam-policy"></a>

 AgentCore CLI 会在部署期间创建代理的执行角色，但该角色不会自动包含令牌库访问权限。您需要附加额外的策略以允许代理在运行时检索 OAuth 2.0 令牌。

此脚本从 Amazon CLI 检索您的账户和区域，从 CloudFormation 堆栈中查找代理的执行角色，并附加相应的策略。您可以复制并粘贴此脚本，也可以将其保存到文件中并执行。

```
#!/bin/bash

# Get account and region from AWS CLI
AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
REGION=$(aws configure get region)

# Get execution role from CloudFormation stack outputs
EXECUTION_ROLE=$(aws cloudformation describe-stack-resources \
  --stack-name AgentCore-IdentityQuickstart-prod \
  --query "StackResources[?ResourceType=='AWS::IAM::Role'].PhysicalResourceId" \
  --output text | head -1)

echo "Parsed values:"
echo "Execution Role: $EXECUTION_ROLE"
echo "Account: $AWS_ACCOUNT"
echo "Region: $REGION"

# Create the policy document with proper variable substitution
cat > agentcore-identity-policy.json << EOF
{
"Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AccessTokenVault",
      "Effect": "Allow",
      "Action": [
        "bedrock-agentcore:GetResourceOauth2Token",
        "secretsmanager:GetSecretValue"
      ],
      "Resource": ["arn:aws:bedrock-agentcore:$REGION:$AWS_ACCOUNT:workload-identity-directory/default/workload-identity/*",
        "arn:aws:bedrock-agentcore:$REGION:$AWS_ACCOUNT:token-vault/default/oauth2credentialprovider/AgentCoreIdentityQuickStartProvider",
        "arn:aws:bedrock-agentcore:$REGION:$AWS_ACCOUNT:workload-identity-directory/default",
        "arn:aws:bedrock-agentcore:$REGION:$AWS_ACCOUNT:token-vault/default",
        "arn:aws:secretsmanager:$REGION:$AWS_ACCOUNT:secret:bedrock-agentcore-identity!default/oauth2/AgentCoreIdentityQuickStartProvider*"
      ]
    }
  ]
}
EOF

# Create the policy
POLICY_ARN=$(aws iam create-policy \
    --policy-name AgentCoreIdentityQuickStartPolicy$(LC_ALL=C tr -dc '0-9' < /dev/urandom | head -c 4) \
    --policy-document file://agentcore-identity-policy.json \
    --query 'Policy.Arn' \
    --output text)

# Extract role name from ARN and attach policy
ROLE_NAME=$(echo $EXECUTION_ROLE | awk -F'/' '{print $NF}')
aws iam attach-role-policy \
    --role-name $ROLE_NAME \
    --policy-arn $POLICY_ARN

echo "Policy created and attached: $POLICY_ARN"

# Cleanup
rm agentcore-identity-policy.json
```

## 第 5 步：调用代理
<a name="identity-quick-start-invoke"></a>

现在一切都设置好了，你可以调用代理了。在本演示中，我们将使用`agentcore invoke`命令和我们的 IAM 证书。使用 IAM 身份验证时，我们需要传递`--user-id`和`--session-id`参数。

```
agentcore invoke "TestPayload" --runtime IdentityQuickstart --user-id "SampleUserID" --session-id "ALongThirtyThreeCharacterMinimumSessionIdYouCanChangeThisAsYouNeed"
```

然后，代理将返回您的`agentcore invoke`命令的 URL。将该 URL 复制并粘贴到您的首选浏览器中，然后您将被重定向到授权服务器的登录页面。`--user-id`参数是您向 Id AgentCore entity 出示的用户 ID。`--session-id`参数是会话 ID，其长度必须至少为 33 个字符。

**重要**  
该`--user-id`参数使用 `GetWorkloadAccessTokenForUserId` API 路径，该路径将 UserID 视为不透明的字符串，而不对照经过身份验证的最终用户身份进行验证。这适用于您没有 IdP 代币的快速入门和开发场景。对于使用 JWT 识别最终用户的生产部署，请改用 JWT-based 身份验证路径 (`GetWorkloadAccessTokenForJWT`)，该路径会验证令牌的发行者、签名和到期时间。有关更多信息，请参阅[获取工作负载访问令牌](get-workload-access-token.md)。

当浏览器出现提示时，在授权服务器上输入用户的用户名和密码，或使用您配置的首选身份验证方法。如果您使用步骤 1 中的脚本创建 Cognito 实例，则可以从终端历史记录中检索该实例。

您的浏览器应重定向到您配置的 OAuth2 回调 URL，该网址处理[会话绑定流程。](https://docs.amazonaws.cn/bedrock-agentcore/latest/devguide/oauth2-authorization-url-session-binding.html)确保您的 OAuth2 回调服务器提供明确的成功和错误响应以指示授权状态。

**注意**  
如果您在未完成授权的情况下中断调用，则可能需要使用新的会话 ID（`--session-id`参数）请求新的 URL。

### 调试
<a name="identity-quick-start-debugging"></a>

如果您遇到任何错误或意外行为，Amazon CloudWatch 日志中会捕获代理的输出。运行`agentcore deploy`后会提供日志尾随命令。

## 清理
<a name="identity-quick-start-cleanup"></a>

完成后，运行，`agentcore remove all`然后`agentcore deploy`从项目目录中删除已部署的 AgentCore 运行时资源。然后删除 Amazon Cognito 用户池，分离并删除您创建的 IAM 政策，并删除凭证提供商。

## 安全最佳实践
<a name="identity-quick-start-security"></a>

处理身份信息时：

1.  **切勿在代理代码**中对凭据进行硬编码

1.  **使用环境变量或 SageMaker Amazon AI ** 获取敏感信息

1.  **配置 IAM 权限**时应用最小权限原则

1.  **定期轮**换外部服务的证书

1.  **审核访问日志**以监控代理活动

1.  ****对身份验证失败实施正确的错误处理