12
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Amazon Bedrock AgentCore]エージェント呼び出し時の認証を実装してみる(Inbound Auth解説)

Posted at

はじめに

Amazon Bedrock AgentCoreのIdentity機能を使うと、「誰が」「どの権限で」アクセスしているのかを安全に識別することができます。

外部からRuntimeを呼び出すときに使われる インバウンド認証(Inbound Auth) は、 エージェントのセキュリティやパーソナライズを支える際重要になります。

本記事では、Amazon Bedrock AgentCoreの認証機能の中でも「エージェントを呼び出すときの認証」 のInbound Auth(インバウンド認証)に焦点をあてて解説します。

また、今回陥った(沼った)エラーの紹介や対象方法なんかも書き残していこうと思います。

認証認可などこの辺はまともにドキュメントを読むと闇堕ち確定なので、学習方法はかんがえないといけません..

Bedrock AgentCore Identity

image.png
Bedrock AgentCore Identityってなんやねん!となるかもなので、
コンソールに分かりやすい画像があったので拝借しつつ、、、

Identity機能について

Amazon Bedrock AgentCore では、エージェントを「誰が」「どのような権限で」呼び出しているのかを識別するための仕組みとして Identity が用意されています。
そんなIdentityには大きく二種類の認証があります。

Inbound Auth

  • エージェントを「呼び出す」時の認証
  • 誰がエージェントにアクセスできるか、誰がしているかを確かめる
  • ユーザーの認証(身元確認)は今回、Cognitoを利用しています!

Outbound Auth

  • エージェントが「外部サービスを呼びだす」ための認証
  • Gateway機能と連携することで、SlackやGoogleドライブといったサードパーティのツールと連携できます。

また、過去にGatewayの記事を書いていました。

要はエージェントとそれを呼び出す側の認証機能ですね!
今回はInbound認証に焦点を当てて記事を書いていきます!

何をしているのか

ここで中の処理について少し詳しく見ていきたいと思います。
Runtime へのリクエスト時、クライアント側は Authorization: Bearer のようにアクセストークンを付与して呼び出します。

agentcore invoke '{"prompt": "Hello what is 1+1?"}' --bearer-token ADD_TOKEN_HERE

このトークンを Runtime が受け取ると、設定された認証エンドポイント(例:Amazon Cognito、Auth0、あるいは独自のOAuthサーバーなど)を通してトークンの検証を行います。

検証が成功すると、Runtime はユーザーの情報(ID、ロール、権限など)を Identity Context として内部に保持し、エージェント実行時にその情報を引き継ぎます。
このとき、エージェントはリクエストがどのユーザーからのものかを認識できるようになり、必要に応じてユーザーごとに動作を変えることができます。

なぜエージェントで認証が重要になるのか

Bedrock AgentCore を使うと、Lambda や外部 API、社内システムなどを「ツール」として組み込み、自然言語でそれらを操作できるようになりますが、同時に「誰が」「何を」「どこまで」操作できるのかをしっかり制御しないと、誰でもAIにアクセスできる、誰でもツールにアクセスできる、といったことになり、セキュリティ面で大きなリスクが生まれますね。

image.png

こうした要件を満たすために、エージェント呼び出し時の認証(Inbound Auth) が重要になります。
Runtime がアクセストークンを検証し、正当なユーザーだけがアクセスできるようにすることで、意図しないツール実行やデータ漏えいを防げます。

image.png

また、認証情報によってはユーザーIDやロールがエージェントに渡されるため、パーソナライズや権限ベースの動作制御も可能になります。
たとえば「管理者だけが特定のLambdaを実行できる」「ユーザーごとに回答の内容を変える」といった細かい制御ができます。

開発初期のうちはつい後回しにしがちな部分ですが、実際に運用を考えるとここが一番大事になります。

構成図

今回実装したのは、下図の赤枠部分にあたる Inbound Auth(インバウンド認証) の部分です。
これは、エージェントを呼び出すクライアント(Caller)が送ってくるリクエストを Runtime 側で検証 し、正しいトークンを持つユーザーだけがエージェントを実行できるようにする仕組みです。

image.png

Inbound Auth を導入することで、誰でもエージェントにアクセスできてしまう状態を防ぎ、社内アプリケーションや限定公開のBotなどを安全に運用できるようになります。
実際には、Runtime 側で authConfig の設定を行い、issuerUrl や audience を指定することで、トークン検証が自動的に行われる仕組みになっています。

実装編

Cognitoユーザープールの作成

setup_cognito.sh
#!/bin/bash

# ユーザープール作成
export POOL_ID=$(aws cognito-idp create-user-pool \
  --pool-name "MyUserPool" \
  --policies '{"PasswordPolicy":{"MinimumLength":8}}' \
  --region $REGION | jq -r '.UserPool.Id')

# アプリクライアント作成
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')

# ユーザー作成
aws cognito-idp admin-create-user \
  --user-pool-id $POOL_ID \
  --username $USERNAME \
  --region $REGION \
  --message-action SUPPRESS > /dev/null

# 永続パスワード設定
aws cognito-idp admin-set-user-password \
  --user-pool-id $POOL_ID \
  --username $USERNAME \
  --password $PASSWORD \
  --region $REGION \
  --permanent > /dev/null

# アクセストークン取得
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')

# 出力
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"
ターミナル
# 環境変数設定
export REGION=us-west-2
export USERNAME=testuser 
export PASSWORD=YourPassword123!

# スクリプトファイル実行
source setup_cognito.sh

このスクリプトファイルを実行すると、認証情報のCognitoユーザープールが作成されるとともに、
以下のような認証情報が出力されるので、控えておいてください!

ターミナル
Discovery URL: ************
Client ID: ************
Bearer Token: ***********

このスクリプトを実行後、以下のようにユーザー認証用のユーザープールが作成されていることがマネコン上からも確認できます〜

image.png

エージェントの実装

ではいよいよメインのエージェントを作成していきます。
ですが、今回はかなりシンプル。
認証されたユーザーだけが、エージェントを呼び出せることを確認します。

まずエージェントのメインコードは以下になります。

AgentCore_Identity.py
from strands import Agent
from bedrock_agentcore.runtime import BedrockAgentCoreApp

agent = Agent(
    model="global.anthropic.claude-haiku-4-5-20251001-v1:0"
)
app = BedrockAgentCoreApp()

@app.entrypoint
def invoke(payload):
    """ユーザー入力を処理してレスポンスを返す"""
    user_message = payload.get("prompt", "")
    response = agent(user_message)
    return str(response)

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

エージェントのデプロイ

ターミナル
uv run agentcore configure --entrypoint AgentCore_Identity.py    
ターミナル
🔐 Authorization Configuration
By default, Bedrock AgentCore uses IAM authorization.
Configure OAuth authorizer instead? (yes/no) [yes]: 

📋 OAuth Configuration
Enter OAuth discovery URL: 
Enter allowed OAuth client IDs (comma-separated): 
Enter allowed OAuth audience (comma-separated):
✓ OAuth authorizer configuration created

🔒 Request Header Allowlist
Configure which request headers are allowed to pass through to your agent.
Common headers: Authorization, X-Amzn-Bedrock-AgentCore-Runtime-Custom-*
Configure request header allowlist? (yes/no) [yes]:

📋 Request Header Allowlist Configuration
Enter allowed request headers (comma-separated) [Authorization,X-Amzn-Bedrock-AgentCore-Runtime-Custom-*]: Authorization,X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id
✓ Request header allowlist configured with 2 headers
Configuring BedrockAgentCore agent: AgentCore_Identity

スターターツールキットを使用すると普段はボタンをぽちぽちするだけですが、今回はエージェントに認証機能をつけたいこともあり、以下の項目に値を入力する必要があります。

  • Enter OAuth discovery URL:: スクリプト実行時に控えていたURLを入力
  • Enter allowed OAuth client IDs: スクリプト実行時に控えていたClient IDを入力
  • Enter allowed OAuth audience:空欄でOK、そのままEnter
  • Request Header Allowlist:これはRuntime に対してユーザーが任意のリクエストヘッダを通過させられるようにする設定です。

今回は以下の2種類のヘッダーを許可しています。

requestHeaderAllowlist:
  - Authorization
  - X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id

Authorization
Bearer Token(Cognitoのアクセストークン)をRuntimeに渡すため。OAuth認証の中核。

X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id
独自に設定したユーザー識別ヘッダ。具体的なユーザー名などを渡して、Runtime 内で利用者を特定・ログ分離などに使う。

configureコマンドを実行したらその後、launchコマンドを実施してあげます。

ターミナル
uv run agentcore launch 

Bearer(ベアラー) Tokenとは

はい、そこのあなた、Bearer Tokenってなんだよ!って思いましたよね?
なので軽く解説します。
今回の例で言うと、Cognitoからエージェントに渡される、「認証済みの証明書」のようなものです。
「ログイン済み」、「この人は認証済み」なのでエージェンントを呼び出していいよと言うのを証明書として、エージェントに伝えるものです。
エージェント呼び出し時にこの証明書を一緒に渡すことで、エージェント「こいつは認証済みのユーザーだ!」と判断することができます。
この一連の中で証明書の役割をしているのが「Bearer Token」です。

CognitoからBearer Tokenを取得する

エージェントを呼び出す前に、Cognito にログインして Bearer Token(アクセストークン)を取得する必要があります。
以下のコマンドで環境変数「$TOKEN」にトークンを保存しています。
ちなみに、ここで取得しているトークンの有効期限1時間です。
時間が経ったら再取得する必要があります。

ターミナル
export TOKEN=$(
  aws cognito-idp initiate-auth \
    --client-id "$CLIENT_ID" \
    --auth-flow USER_PASSWORD_AUTH \
    --auth-parameters USERNAME=$USERNAME,PASSWORD=$PASSWORD \
    --region us-west-2 \
  | jq -r '.AuthenticationResult.AccessToken'
)

以下のコマンドで環境変数にトークン変数が入っているか確認できます。
実施前、エラーになった時など、環境変数にしっかりトークンが格納されているかの確認に使えます。

ターミナル
echo "$TOKEN"

動作確認編

さて、ここまででエージェントを呼び出す準備はできましたのでいよいよ動作確認です。
まずは以下のコマンドで呼び出してみましょう。
トークンの指定とユーザーの識別をヘッダーに追加で記述しています。

ターミナル
uv run agentcore invoke '{"prompt": "こんにちは!今日もいい日ですね!"}' \
  --agent AgentCore_Identity \
  --bearer-token "$TOKEN" \
  --headers "X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id: yakumo_0905"

うまくいくと、以下のように認証がうまくいった旨のログが出たのち、レスポンスが返ってきます!
ここまででIdentity機能のインバウンド認証は作ることができました!

ターミナル
Using bearer token for OAuth authentication
Using custom headers: X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id
╭─────────────────────────────────────────────────────────────────────────────────────────────── AgentCore_Identity ────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Session: b5f9f074-231e-4fe9-98a0-5a6dd9cf7689                                                                                                                                                                     │
│ ARN: arn:aws:bedrock-agentcore:us-west-2:017820658462:runtime/AgentCore_Identity-4ndgCLFUkw                                                                                                                       │
│ Logs: aws logs tail /aws/bedrock-agentcore/runtimes/AgentCore_Identity-4ndgCLFUkw-DEFAULT --log-stream-name-prefix "2025/11/12/[runtime-logs" --follow                                                            │
│       aws logs tail /aws/bedrock-agentcore/runtimes/AgentCore_Identity-4ndgCLFUkw-DEFAULT --log-stream-name-prefix "2025/11/12/[runtime-logs" --since 1h                                                          │
│ GenAI Dashboard: https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen-ai-observability/agent-core                                                                                                  │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Response:
こんにちは!ありがとうございます😊

こちらこそ、素敵なご挨拶をいただきました。

今日一日、何かお手伝いできることがあればお気軽にお聞きください。何でもお答えしますよ!

では、認証情報のヘッダーなしで呼び出すとどうなるのでしょうか?
試してみます。

ターミナル
uv run agentcore invoke '{"prompt": "こんにちは!今日もいい日ですね!"}'  

以下のように、認証情報を渡さないとエラーになりますね。
これが確認できれば本当にOKです

ターミナル
Warning: OAuth is configured but no bearer token provided
╭─────────────────────────────────────────────────────────────────────────────────────────────── AgentCore_Identity ────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Session: b5f9f074-231e-4fe9-98a0-5a6dd9cf7689                                                                                                                                                                     │
│ Request ID: 5c0c8563-92dc-4674-9253-5c9efa3be5d6                                                                                                                                                                  │
│ ARN: arn:aws:bedrock-agentcore:us-west-2:017820658462:runtime/AgentCore_Identity-4ndgCLFUkw                                                                                                                       │
│ Logs: aws logs tail /aws/bedrock-agentcore/runtimes/AgentCore_Identity-4ndgCLFUkw-DEFAULT --log-stream-name-prefix "2025/11/12/[runtime-logs" --follow                                                            │
│       aws logs tail /aws/bedrock-agentcore/runtimes/AgentCore_Identity-4ndgCLFUkw-DEFAULT --log-stream-name-prefix "2025/11/12/[runtime-logs" --since 1h                                                          │
│ GenAI Dashboard: https://console.aws.amazon.com/cloudwatch/home?region=us-west-2#gen-ai-observability/agent-core                                                                                                  │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Invocation failed: An error occurred (AccessDeniedException) when calling the InvokeAgentRuntime operation: Authorization method mismatch. The agent is configured for a different authorization method than what was
used in your request. Check the agent's authorization configuration and ensure your request uses the matching method (OAuth or SigV4)

トラブルシューティングまとめ

ここに私が今回沼ったトラブルシューティングを載せておきます。
これが誰かの助けになれば幸いです。

Request Header Allowlist 設定を忘れた場合

エラー内容

ターミナル
An error occurred (ValidationException) when calling the UpdateAgentRuntime operation:
Value '[X-Amzn-Bedrock-AgentCore-Runtime-User-Id]' failed to satisfy constraint

原因

AgentCore Runtime は、許可リストにないヘッダを拒否します。
たとえば Authorization や X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id を使いたい場合、
configure時に許可しておかないと Validation Error になります。

解決策

agentcore configure 実行時に必要な情報を入力

ターミナル
Configure request header allowlist? (yes/no) [no]: yes
Enter comma-separated list of headers to allow:
Authorization,X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id

設定後、再度 agentcore launch を実行し、Runtime を再デプロイ。

Authorization method mismatch エラー

エラー内容

ターミナル
AccessDeniedException: Authorization method mismatch.
The agent is configured for a different authorization method than what was used in your request.

原因

Runtime の authorizer_configuration が CustomJWTAuthorizer(Cognito連携) なのに、CLI 側が SigV4 署名やヘッダ渡し (--headers "Authorization: Bearer $TOKEN") で呼び出していたため

解決策

CLIでは --bearer-token オプションを使用する必要がありました。

ターミナル
uv run agentcore invoke '{"prompt": "こんにちは"}' \
  --agent AgentCore_Identity \
  --bearer-token "$TOKEN" \
  --headers "X-Amzn-Bedrock-AgentCore-Runtime-Custom-User-Id: yakumo_0905"

403 Client Error: Forbidden が発生する

エラー内容

ターミナル
Failed to invoke agent endpoint: 403 Client Error: Forbidden for url:
https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/...

原因

allowedAudienceを空欄ではなくアクセストークンを入力していた

解決策

configureコマンド時に空のままEnter押下

さいごに

今回は、Amazon Bedrock AgentCore の Inbound Auth(エージェント呼び出し時の認証) を実装してみました。
実際に触ってみると、設定項目自体はシンプルですが、「認証を通す」=「ユーザーを識別できるようにする」 という点が非常に重要だと感じました。

Bedrock AgentCore は外部から自然言語で呼び出せる仕組みが強力な反面、アクセス制御を誤ると誰でもエージェントを操作できてしまう可能性があります。
今回のように Inbound Auth をきちんと設定しておくことで、安全な運用の基盤を作ることができます。

また、Cognito などの既存の認証基盤と組み合わせることで、個人ごとのパーソナライズや権限ベースの制御も自然に組み込める点は大きな魅力です。
次回は外部サービス連携時の Outbound Authの記事も書こうと思います。

12
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?