本記事では、Amazon Bedrock AgentCore Runtime の認証を SigV4 と JWT(Cognito) の2軸で整理してみました。
以前、GitHub 公式 MCP サーバを「無改変のまま」AgentCore Runtime に載せたのですが、その過程で「Runtime をどう認証して呼ぶのか」が地味に重要かつ混乱しやすいポイントだと感じたので、今回はそこを深掘りします。
TL;DR
- AgentCore Runtime のインバウンド認証は SigV4(IAM) と JWT(OAuth/OIDC) の2種類。呼ぶ主体によって使い分ける(あくまで目安。サーバ間でも JWT を使うことはあります)。
- サーバ間(バックエンド → Runtime)は SigV4 が手軽
- エンドユーザー(ブラウザ → Runtime)は JWT
- JWT は CDK の
RuntimeAuthorizerConfiguration.usingJWT(discoveryUrl, allowedClients)で設定する。 -
ハマった点: Cognito では 「アクセストークン」を渡す(IDトークンだと
client_id mismatchで 401)。 -
ハマった点: SigV4 は
Authorizationヘッダを使うので、追加トークンは別ヘッダにする(前回のX-Github-Tokenの話)。 - 認証設定は CLI(
get-agent-runtime)で確認できるが、マネコンには現状出てこない。
前提: リージョンは
ap-northeast-1、AWSアカウントは伏せ字(123456789012)で記載します。フロントは React、エージェントは Python(Strands)、IaC は AWS CDK(TypeScript) という構成です(AWS Labs の FAST テンプレートベース)。
AgentCore Runtimeの認証は2種類ある
AgentCore Runtime を InvokeAgentRuntime で呼ぶとき、Runtime 側で受け付ける認証方式は次の2つです。
| SigV4 (IAM) | JWT Bearer (OAuth/OIDC) | |
|---|---|---|
| 認証する相手 | AWS の IAM プリンシパル | IdP が発行した JWT(例: Cognito) |
| 渡し方 | リクエストを AWS資格情報でSigV4署名 |
Authorization: Bearer <JWT> ヘッダ |
| 既定 | デフォルト | 明示的に設定が必要 |
| 向いている用途 | サーバ間(バックエンド → Runtime) | エンドユーザー(ブラウザ/アプリ → Runtime) |
| 呼ぶ側の準備 | IAM権限 bedrock-agentcore:InvokeAgentRuntime
|
Runtime側にJWT authorizer設定 |
「どちらか一方が正解」ではなく、呼ぶ主体によって適切な方が違うのがポイントです。
実際の構成: どこでSigV4、どこでJWTか
今回のアプリでは AgentCore Runtime が2つ登場し、それぞれ認証方式が違います。
[ブラウザ(React)]
│ ① JWT(Cognitoアクセストークン)を Authorization: Bearer で送信
▼
[アプリのエージェントRuntime (Strands)]
│ ② SigV4(実行ロールのAWS資格情報で署名)
▼
[GitHub MCPのRuntime (以前作ったもの)]
└─→ GitHub
-
① ブラウザ → アプリRuntime = JWT
ユーザーが Cognito でログインし、発行された アクセストークンをAuthorization: Bearerに載せて Runtime を直接呼びます。 -
② エージェント → MCP Runtime = SigV4
エージェント(サーバ側)が別Runtimeを呼ぶときは、実行ロールのAWS資格情報で SigV4署名します。
なぜブラウザはSigV4を使わないのか
SigV4署名には AWSのアクセスキー/シークレットが要ります。これを公開されるブラウザに置くのは論外です。そこで、エンドユーザー向けには IdP(Cognito)のJWT を使う、というのが定石で、AgentCore Runtime もこのために JWT authorizer をサポートしています。逆にサーバ間(②)は IAMロールで完結するので SigV4 が自然、という整理です。
ただし「サーバ間=必ずSigV4」というわけでもありません。例えばエージェントが別のエージェントを呼ぶようなサーバ間通信でも、呼び出し元のユーザーIDや権限をトークンで伝えたいケースでは JWT を選ぶこともあります。ここはユースケース次第(ケースバイケース)です。SigV4 は「とりあえず IAM だけで通せる手軽さ」、JWT は「IdP に紐づくアイデンティティ/スコープを運べる」のが強み、という感覚で捉えています。
工夫①: JWT(Cognito)をCDKで設定する
AgentCore の CDK 構築子では、RuntimeAuthorizerConfiguration.usingJWT() で JWT authorizer を設定できます。
// 1. authorizer を定義
const authorizerConfiguration = agentcore.RuntimeAuthorizerConfiguration.usingJWT(
// discoveryUrl: Cognito の OIDC ディスカバリ URL
`https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/openid-configuration`,
// allowedClients: 許可するアプリクライアントIDの一覧
[userPoolClientId]
)
// 2. Runtime に紐付け
new agentcore.Runtime(this, "Runtime", {
agentRuntimeArtifact,
// ...
authorizerConfiguration, // ← ここで適用
})
これは内部的に CloudFormation の AWS::BedrockAgentCore::Runtime CustomJWTAuthorizerConfiguration に展開されます。設定する中身は実質2つだけです。
| プロパティ | 値の例 | 役割 |
|---|---|---|
| discoveryUrl | https://cognito-idp.ap-northeast-1.amazonaws.com/<userPoolId>/.well-known/openid-configuration |
署名検証用の公開鍵(JWKS)と発行者情報を取得し、トークンの署名・発行者を検証 |
| allowedClients | ["<appClientId>"] |
トークンの client_id クレームがこの一覧に含まれるかを検証 |
discoveryUrl は必須。allowedClients(または allowedAudience)で「誰のトークンを信頼するか」を絞ります。
JWKS は JSON Web Key Set の略で、JWT の署名を検証するための公開鍵のセット(JSON)です。discoveryUrl(
.well-known/openid-configuration)の中にjwks_uriが書かれており、Runtime はそこから鍵を取得してトークンの署名を検証します。鍵のローテーションにも追従できるので、Runtime 側に鍵を直接埋め込む必要がありません。
工夫②: 呼ぶ側(ブラウザ)の実装
ブラウザからは Runtime のデータプレーンに直接 fetch します。
const url =
`https://bedrock-agentcore.${region}.amazonaws.com` +
`/runtimes/${encodeURIComponent(runtimeArn)}/invocations?qualifier=DEFAULT`
const res = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`, // ← Cognitoアクセストークン(JWT)
"Content-Type": "application/json",
"X-Amzn-Bedrock-AgentCore-Runtime-Session-Id": sessionId, // セッション識別(認証とは別)
},
body: JSON.stringify({ prompt, runtimeSessionId: sessionId }),
})
Runtime はトークンを検証したあと、その sub クレームをユーザーIDとして扱えます。per-user のデータ参照や認可の起点に使えて便利です。
ハマりどころ集
① 「アクセストークン」か「IDトークン」か
ここが一番ハマりました。Cognito は「IDトークン」と「アクセストークン」の2種類を発行しますが、AgentCore の JWT authorizer に渡すのはアクセストークンです。
-
IDトークン …
aud(audience) は持つがclient_idは持たない -
アクセストークン …
client_idを持つ
ところが usingJWT(..., allowedClients) は client_id を検証します。なのでIDトークンを渡すと、
401 Unauthorized (client_id mismatch)
になります。react-oidc-context を使っているなら auth.user?.access_token が正解です(id_token ではない)。
② SigV4と「Authorizationヘッダ」の競合
SigV4は署名を Authorization ヘッダに入れます。一方で下流(GitHub)に渡したいトークンも Authorization に入れたい……と競合します。
そこで以前の記事では、GitHub の PAT を X-Github-Token という別ヘッダで持ち回り、受け側(nginx)で Authorization: Bearer に詰め替える、という方式にしました。SigV4を使うときは、追加で運びたいトークンは別ヘッダにする、と覚えておくと安全です。
③ 設定がマネコンに出てこない
JWT authorizer を設定したあと、「マネコンのどこで確認できるんだろう?」と探したのですが、2026年6月現在、AgentCore のコンソール(Runtime詳細画面)に authorizer 設定は表示されませんでした。コンソールで見えるのはステータス・ARN・エンドポイント・オブザーバビリティあたりです。
「コンソールに出ない=設定されていない」ではないので、確認は次の CLI でやりましょう。
AgentCore はまだ新しいサービスなので、このあたりは今後コンソールでも見えるように対応されていく気がします(あくまで個人の予想です)。
設定の確認方法(CLIが一次情報)
設定の実体は、API/CLI で確実に確認できます(読み取りのみ)。
aws bedrock-agentcore-control get-agent-runtime \
--agent-runtime-id <runtimeId> \
--region ap-northeast-1
レスポンスの authorizerConfiguration.customJWTAuthorizer に discoveryUrl と allowedClients が入っていれば、JWT 認証が効いていて、どの IdP/クライアントを信頼しているかが分かります。
確認は CLI(
get-agent-runtime)、正本は IaC(CDK のusingJWT(...)定義) を見るのが確実、という整理に落ち着きました。
まとめ
- AgentCore Runtime のインバウンド認証は SigV4(IAM) と JWT(OAuth/OIDC) の2種類。呼ぶ主体で使い分ける。
- サーバ間 → SigV4 / エンドユーザー → JWT
- JWT は CDK の
usingJWT(discoveryUrl, allowedClients)で設定。実体はCustomJWTAuthorizerConfiguration。 -
Cognitoではアクセストークンを渡す(
client_idを検証するため。IDトークンだと401)。 - SigV4利用時は
Authorizationを使うので、追加トークンは別ヘッダに(前回のX-Github-Token)。 - 認証設定は CLI(
get-agent-runtime) と IaC で確認。コンソールには現状出ない。
AgentCore は「Runtime をどう呼ぶか/どう守るか」を、用途に応じて IAM と OIDC で素直に切り替えられるのが分かりやすいと感じました。同じことをやりたい方の参考になれば幸いです。