

# 最初の認証済みエージェントを構築する
<a name="identity-getting-started-cognito"></a>

この入門チュートリアルでは、Amazon Bedrock AgentCore Identity を使用して完全に認証されたエージェントをゼロから構築する手順について説明し、エージェントアプリケーションで ID 機能の実装を開始するのに役立ちます。開発環境をセットアップし、Cognito で認証インフラストラクチャを作成し、エージェントを AgentCore ランタイムにデプロイして、完全な認証ワークフローをテストする方法について説明します。

このチュートリアルを終了すると、OAuth2 フローを通じてユーザーを認証し、アクセストークンを安全に取得し、完全な ID 管理ライフサイクルを示すことができる、完全にデプロイされたエージェントが作成されます。エージェントは適切な IAM アクセス許可を持つ AgentCore ランタイムで実行され、統合機能をデモンストレーションしてテストできるテストラボ環境が作成されます。

**Topics**
+ [前提条件](#identity-quick-start-prerequisites)
+ [ステップ 1: Cognito ユーザープールを作成する (オプション)](#identity-quick-start-cognito)
+ [ステップ 2: 認証情報プロバイダーを作成する](#identity-quick-start-credential-provider)
+ [ステップ 2.5: OAuth 2.0 認可サーバーにコールバック URL を追加する](#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>

開始する前に、以下があることを確認してください。
+ 適切なアクセス許可を持つ AWS アカウント
+ Python 3.10 以降がインストールされている
+ 最新の CLI AWS と `jq`がインストールされている
+ Node.js 18\+ がインストールされている (AgentCore CLI の場合)
+  AWS 認証情報とリージョンの設定 ( `aws configure` )

このチュートリアルでは、OAuth 2.0 認可サーバーが必要です。持っていない場合は、ステップ 1 で Amazon Cognito ユーザープールを使用して作成します。クライアント ID、クライアントシークレット、およびユーザーが設定された OAuth 2.0 認可サーバーがある場合は、ステップ 2 に進むことができます。この認可サーバーはリソース認証情報プロバイダーとして機能し、エージェントにアウトバウンド OAuth 2.0 アクセストークンを付与する権限を表します。

### SDK と依存関係をインストールする
<a name="identity-quick-start-install"></a>

このガイドのフォルダを作成し、Python 仮想環境を作成し、AgentCore SDK と Python SDK (boto3) AWS をインストールします。

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

また、次の内容の `requirements.txt` ファイルを作成します。これは、後で AgentCore デプロイツールで使用されます。

```
bedrock-agentcore
boto3
pyjwt
strands-agents
```

## ステップ 1: Cognito ユーザープールを作成する (オプション)
<a name="identity-quick-start-cognito"></a>

このチュートリアルでは、OAuth 2.0 認可サーバーが必要です。テストに使用できるものがない場合、またはテストを認可サーバーとは別に保持する場合、このスクリプトは AWS 認証情報を使用して 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: OAuth 2.0 認可サーバーにコールバック URL を追加する
<a name="identity-update-credential-provider"></a>

不正なリダイレクトを防ぐには、[CreateOauth2CredentialProvider](https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_CreateOauth2CredentialProvider.html) または [GetOauth2CredentialProvider](https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_GetOauth2CredentialProvider.html) から取得したコールバック URL を OAuth 2.0 認可サーバーに追加します。

前のスクリプトを使用して Cognito で認可サーバーを作成する場合は、出力からターミナルに EXPORT ステートメントをコピーして環境変数を設定し、Cognito ユーザープールクライアントを OAuth2 認証情報プロバイダーコールバック URL で更新します。

```
#!/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.aws.amazon.com/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-tutorials/03-AgentCore-identity/05-Outbound_Auth_3lo/oauth2_callback_server.py)

## ステップ 4: エージェントを AgentCore ランタイムにデプロイする
<a name="identity-quick-start-deploy"></a>

このエージェントは AgentCore ランタイムでホストされます。AgentCore CLI を使用すると、これを簡単に行うことができます。

ターミナルから AgentCore CLI をインストールし、新しいプロジェクトを作成します。

```
npm install -g @aws/agentcore
agentcore create --name IdentityQuickstart --defaults
```

エージェントスクリプトをプロジェクトのエージェントディレクトリにコピーし、デフォルトのエージェントを置き換えます。

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

また、要件ファイルをエージェントディレクトリにコピーして、すべての依存関係がデプロイに含まれていることを確認します。

```
cp requirements.txt IdentityQuickstart/app/IdentityQuickstart/
```

次に、プロジェクトをデプロイします。

```
cd IdentityQuickstart
agentcore deploy
```

CLI は AWS CDK スタックを合成し、エージェントを AgentCore ランタイムにデプロイします。これには約 2～3 分かかります。

### トークンボールトとクライアントシークレットにアクセスできるようにエージェントの IAM ポリシーを更新する
<a name="identity-quick-start-iam-policy"></a>

AgentCore CLI はデプロイ中にエージェントの実行ロールを作成しますが、ロールにはトークンボールトアクセスのアクセス許可が自動的に含まれません。エージェントが実行時に OAuth 2.0 トークンを取得できるようにするには、追加のポリシーをアタッチする必要があります。

このスクリプトは、 CLI AWS からアカウントとリージョンを取得し、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` パラメータは、AgentCore Identity に提示するユーザー ID です。`--session-id` パラメータはセッション ID で、33 文字以上である必要があります。

**重要**  
`--user-id` パラメータは `GetWorkloadAccessTokenForUserId` API パスを使用します。これは、認証されたエンドユーザー ID に対して検証することなく、userId を不透明な文字列として扱います。これは、IdP トークンが利用できないクイックスタートおよび開発シナリオに適しています。エンドユーザーを識別する JWT がある本番デプロイでは、代わりに JWT ベースの認証パス (`GetWorkloadAccessTokenForJWT`) を使用して、トークンの発行者、署名、有効期限を検証します。詳細については、[「ワークロードアクセストークンの取得](get-workload-access-token.md)」を参照してください。

ブラウザでプロンプトが表示されたら、認可サーバーでユーザーのユーザー名とパスワードを入力するか、設定した任意の認証方法を使用します。ステップ 1 のスクリプトを使用して Cognito インスタンスを作成した場合は、ターミナル履歴から取得できます。

ブラウザは、[セッションバインディングフロー](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/oauth2-authorization-url-session-binding.html) を処理する設定済みの OAuth2 コールバック URL にリダイレクトする必要があります。OAuth2 コールバックサーバーが、認可ステータスを示す明確な成功応答とエラー応答を提供することを確認します。

**注記**  
認可を完了せずに呼び出しを中断する場合、新しいセッション ID ( `--session-id`パラメータ) を使用して新しい URL をリクエストする必要がある場合があります。

### デバッグ
<a name="identity-quick-start-debugging"></a>

エラーや予期しない動作が発生した場合、エージェントの出力は Amazon CloudWatch logsにキャプチャされます。ログ末尾コマンドは、 の実行後に提供されます`agentcore deploy`。

## クリーンアップ
<a name="identity-quick-start-cleanup"></a>

完了したら、プロジェクトディレクトリ`agentcore deploy`から `agentcore remove all`と を実行して、デプロイされた AgentCore ランタイムリソースを破棄します。次に、Amazon Cognito ユーザープールを削除し、作成した IAM ポリシーをデタッチして削除し、認証情報プロバイダーを削除します。

## セキュリティのベストプラクティス
<a name="identity-quick-start-security"></a>

ID 情報を使用する場合:

1.  エージェントコードで**認証情報をハードコードしない** 

1.  機密情報に**環境変数または Amazon SageMaker AI を使用する** 

1.  IAM アクセス許可を設定するときに**最小特権の原則を適用する** 

1.  外部サービスの**認証情報を定期的に更新**する

1.  **アクセスログを監査**してエージェントのアクティビティをモニタリングする

1.  認証の失敗に対して**適切なエラー処理を実装**する