第7章 外部認証を制御する「アイデンティティ」 — 学習メモ¶
書籍「Amazon Bedrock AgentCore実践入門」第7章のサンプルコード(このフォルダ)を読み解いた個人学習メモ。 AgentCore 全体像は
../../lectures/agentcore_basics/STUDY_NOTES.md参照。 実行検証は伴わない。コードに現れた API 名だけ断定し、読めない挙動は「〜と推測」で明示する。
一言で¶
アイデンティティ = エージェントのツールが外部 SaaS(Atlassian 等)の API を呼ぶときの「OAuth 3LO(three-legged OAuth)フローの面倒な部分」を @requires_access_token デコレータ1個に丸ごと肩代わりさせる仕組み。認可URL発行・ユーザー同意・コールバック受信・トークン交換という4段階を、ツール本体のコードから切り離せる。
全体像¶
このフォルダは2つの独立したプロセスから成る。
01_outbound.py: ツール本体。@requires_access_tokenで包んだ関数が Atlassian の API を呼ぶ02_callback_server.py: OAuth の認可完了後のリダイレクトを受け取り、トークン交換を完了させる FastAPI サーバー(http://localhost:9090)
両方を同時に起動しておく必要がある(README)。処理の流れは以下(デコレータ内部の詳細な実装はSDK側にあり、コードから直接読めない部分は「推測」と明示する)。
sequenceDiagram
participant U as ユーザー
participant Ag as Strandsエージェント(01_outbound.py)
participant Dec as requires_access_tokenデコレータ
participant Atl as Atlassian(OAuth認可サーバー)
participant CB as コールバックサーバー(02_callback_server.py)
U->>Ag: Atlassianのサイト一覧を取得して
Ag->>Dec: get_confluence_sites → call_api() を呼ぶ
Dec->>Dec: 認可URLを発行(on_auth_url)
Dec-->>U: 認可URLをprintで表示
U->>Atl: ブラウザで認可URLを開き同意
Atl-->>CB: callback_url(localhost:9090/oauth2/callback)へリダイレクト
CB->>Atl: complete_resource_token_auth(session_uri, user_identifier)
Atl-->>CB: トークン交換完了
Dec->>Dec: access_tokenをcall_apiへ注入
Dec->>Atl: Bearerトークン付きでAPI呼び出し
Atl-->>Dec: レスポンス(JSON)
Dec-->>Ag: 結果を返す
Ag-->>U: 最終応答
- 「Dec→Dec: 認可URLを発行」以降、コールバックサーバーがトークン交換を完了させてから
call_apiにaccess_tokenが注入されるまでの間、デコレータ内部がどう待ち合わせている(ポーリングか、セッション ID をキーにした待機か)かはコードから直接読めない。ここは SDK(bedrock-agentcore)内部の実装なので「〜と推測」の扱いとする。
使用ライブラリ・原理¶
bedrock_agentcore.identity.requires_access_token(bedrock-agentcore==1.6.4): OAuth トークン取得をデコレータで肩代わりする AgentCore Identity の SDKbedrock_agentcore.services.identity.IdentityClient/UserIdIdentifier: コールバック側でトークン交換を確定させるクライアントstrands.Agent/@tool(strands-agents==1.38.0): エージェント本体とツール化デコレータhttpx: ツール内部から Atlassian API を叩く HTTP クライアントfastapi+uvicorn: コールバックサーバーの実装
ファイル別の役割¶
| ファイル | 役割 |
|---|---|
01_outbound.py |
ツール実装。@requires_access_token で包んだ関数が OAuth トークンを使って Atlassian API を呼ぶ |
02_callback_server.py |
OAuth 認可完了後のリダイレクトを受け取り、complete_resource_token_auth でトークン交換を完了させる FastAPI サーバー |
pyproject.toml |
依存関係の固定(strands-agents==1.38.0, bedrock-agentcore==1.6.4 等、requires-python >= 3.14) |
中心コードの読み解き¶
01_outbound.py¶
@requires_access_token(
provider_name="AtlassianProvider",
scopes=["read:confluence-content.all"],
auth_flow="USER_FEDERATION",
on_auth_url=lambda url: print(url),
callback_url="http://localhost:9090/oauth2/callback",
)
def call_api(access_token: str = ""):
response = httpx.get(
"https://api.atlassian.com/oauth/token/accessible-resources",
headers={"Authorization": f"Bearer {access_token}"},
)
return response.json()
| 行 | やってること | なぜ |
|---|---|---|
01_outbound.py:10-16 |
@requires_access_token で call_api を包む |
OAuth 3LO のトークン取得処理をデコレータに委譲し、ツール本体は API 呼び出しに専念できる |
01_outbound.py:11 |
provider_name="AtlassianProvider" |
事前にマネコン等で登録した OAuth プロバイダー設定を名前で参照するキー。コードだけでは動かず、書籍本文の手順で先に登録が必要(README) |
01_outbound.py:13 |
auth_flow="USER_FEDERATION" |
ユーザー単位で認可させる 3LO(three-legged OAuth)モードの指定 |
01_outbound.py:14 |
on_auth_url=lambda url: print(url) |
認可URLが発行されたときのコールバック。ここでは print するだけで、ブラウザを自動で開かない |
01_outbound.py:17 |
access_token: str = "" |
デコレータがトークン取得完了後にこの引数へ実際の値を注入する |
02_callback_server.py¶
client = IdentityClient(region="us-east-1")
config = json.load(open(".agentcore.json"))
@app.get("/oauth2/callback")
async def handle_callback(session_id: str):
client.complete_resource_token_auth(
session_uri=session_id,
user_identifier=UserIdIdentifier(
user_id=config["user_id"]))
return "認証成功!このタブを閉じてください"
| 行 | やってること | なぜ |
|---|---|---|
02_callback_server.py:7 |
IdentityClient(region="us-east-1") |
AgentCore Identity の API を呼ぶクライアントを生成 |
02_callback_server.py:8 |
config = json.load(open(".agentcore.json")) |
user_id を外部ファイルから読み込む。同ディレクトリに {"user_id": "..."} の内容を持つ .agentcore.json を配置する必要がある(README) |
02_callback_server.py:11-17 |
/oauth2/callback エンドポイント |
OAuth プロバイダーからのリダイレクトを session_id クエリパラメータで受け取る |
02_callback_server.py:13-16 |
client.complete_resource_token_auth(session_uri=session_id, user_identifier=UserIdIdentifier(user_id=...)) |
セッションとユーザーを突き合わせ、実際の OAuth トークンを AgentCore 側に確定させる。これが完了して初めて 01_outbound.py 側の access_token に値が入る |
02_callback_server.py:20 |
uvicorn.run(app, host="127.0.0.1", port=9090) |
callback_url と一致するポート(9090)で待ち受ける |
学んだこと(要点)¶
- 3LO(three-legged OAuth)の面倒な部分(認可URL生成・コールバック受信・トークン交換)が
requires_access_token1個にラップされている。ツール本体はaccess_tokenを受け取って使うだけでよい - 動かすには2プロセット必要(
01_outbound.pyと02_callback_server.py)。片方だけでは 3LO フローが完結しない on_auth_urlは URL をprintするだけで自動オープンしない(コード上の事実)。ユーザーが手動でコピーしてブラウザを開く必要がある.agentcore.jsonにuser_idを外出しし、コールバックサーバーがそれを読み込む設計。ツール呼び出し元のユーザーとコールバック側のuser_idをどう突き合わせているかの詳細(セッションIDとの紐付けロジック)はコードからは読み切れず、SDK 内部の挙動に依存すると推測される
落とし穴・現代版に移植するなら¶
provider_name="AtlassianProvider"は事前登録が前提。書籍本文の手順で OAuth プロバイダーを作成してからでないとコードだけでは動かない(README)- port 9090 が使用中だった場合は
lsof -i :9090 -t | xargs killで解放できる(README) requires-python = ">=3.14"、strands-agents==1.38.0、bedrock-agentcore==1.6.4で固定されている(pyproject.toml)on_auth_urlをwebbrowser.open(url)に差し替えれば認可URLの自動オープンができそうだが、これはコードから読める事実ではなく改善案としての推測
記事参照¶
- 書籍 第7章。関連:
../../lectures/agentcore_basics/STUDY_NOTES.md(AgentCore 全体像。Identity は8部品の1つ)
作成: 2026-07-17 / 最終更新: 2026-07-17