このレッスンのロックを解除するには、まず「APIをエージェントツールとして設計・利用する」を完了してください。前のレッスンに戻る

なぜエージェントに認証が必要なのか

AIエージェントがデータベース、サードパーティAPI、クラウド関数などの外部サービスを呼び出すとき、自分自身の身元を証明する必要があります。その証明には主に2つの形式があります。1つは静的なAPIキー(サービスから一度発行される長いランダム文字列)、もう1つはOAuth 2.0(エージェントが資格情報を時間制限のあるアクセストークンと交換するプロトコル)を通じて発行される短命トークンです。どちらも目的は共通しており、リモートサーバーが資格情報を確認し、リクエストを受け入れるかどうかを判断します。

危険なのは資格情報そのものではなく、漏洩したときに何が起こるかです。チャットログ、エラートレース、LLMに送信されるpromptに含まれるAPIキーは、数分以内にスクレイピングされて悪用される可能性があります。本番データベースのパスワードと同じくらい慎重にシークレットを扱うことが、基本的な前提です。

2つの認証フローを比較する図 — 各リクエストに紐付く静的なAPIキーと、ハンドシェイクで取得して一時的に使用されるOAuthトークン

シークレットをどこに保存するか

ソースファイルに資格情報をハードコードしないでください。promptテンプレートに貼り付けないでください。標準的なパターンはランタイムで環境変数から読み込むことで、これによりシークレットはコードベースではなくデプロイ環境に保管されます。

python
import os
import requests
api_key = os.environ["WEATHER_API_KEY"]
response = requests.get(
"https://api.weather.example.com/v1/current",
headers={"Authorization": f"Bearer {api_key}"}
)

このスニペットでは、キーを環境から読み込み、HTTPヘッダーのBearerトークンとして付与し、ディスクへの書き込みやログへの出力は一切行っていません。環境変数が存在しない場合、エージェントは誤構成を隠すプレースホルダーに黙ってフォールバックするのではなく、明確な起動エラーで迅速に失敗する必要があります。

ローカル開発では、`.env`ファイル(`.gitignore`でバージョン管理から除外された、key=valueペアを保持するプレーンテキストファイル)が便利です。本番環境では、オーケストレーターまたはシークレットマネージャーが値を注入します。いずれにせよ、ルールは同じです。シークレットはコードの外に置くべきです。

OAuthトークンとリフレッシュフロー

静的なキーはシンプルですが柔軟性に欠けます。OAuthトークンは、エージェントがユーザーに代わって動作する場合(例:ユーザーのカレンダーを読み取ったり、アカウントに投稿したり)に適しています。フローは次のようになります。

bash
# Step 1: agent receives an authorization code after user consent
# Step 2: exchange code for access token + refresh token
curl -X POST https://auth.example.com/oauth/token \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE" \
-d "client_id=AGENT_ID" \
-d "client_secret=AGENT_SECRET"
# Step 3: use the access token until it expires, then refresh

エージェントはアクセストークンをメモリだけに保存し、リフレッシュトークンはセキュアストアに保存する必要があります。アクセストークンが期限切れになった場合(通常は401レスポンスで示されます)、リフレッシュトークンを使って新しいアクセストークンをバックグラウンドで交換します。ユーザーは再同意を求められません。このリフレッシュロジックを小さなヘルパー関数にまとめることで、呼び出し側のコードをきれいに保てます。

Promptやログでの漏洩を防ぐ

エージェントシステムにおける最も一般的な資格情報漏洩は、意図しないエコーバックです。エージェントがLLMに送信するprompt内にシークレットを含めてしまったり、ロガーがヘッダーを含むリクエスト全体を出力してしまうケースです。どちらも、気をつけることで簡単に防げます。

python
def build_prompt(user_query: str, context: dict) -> str:
# Never inject credentials into the prompt
safe_context = {k: v for k, v in context.items() if not k.startswith("secret_")}
return f"Context: {safe_context}\nUser: {user_query}"
def safe_log_request(method, url, headers):
# Strip Authorization header before logging
redacted = {k: ("***" if k.lower() == "authorization" else v) for k, v in headers.items()}
print(f"{method} {url} headers={redacted}")

1つ目の関数は、名前にシークレットの兆候があるコンテキストフィールドをすべて除外します。2つ目は、出力前にAuthorizationヘッダーを黒塗りします。スタックトレース、エラーレポート、ユーザーに表示されるエラーメッセージにも同じサニタイズ処理を適用してください。スタックトレースにトークンが含まれていたら、その時点で既に漏洩しています。

まとめ

3つのルールで大抵のケースをカバーできます。まず、資格情報はコードやpromptではなく環境から読み込むこと。次に、サービスでOAuthがサポートされている場合は、長期間有効なキーよりも短命なトークンを優先し、自動でリフレッシュすること。そして3つ目に、すべてのログ行、エラーメッセージ、promptを潜在的な漏洩経路とみなし、書き出す前に黒塗り処理を行うこと。この3つのルールに従ってもシステムを万全にするわけではありませんが、実際に攻撃者が侵入してくる経路は塞ぐことができます。

レッスンの練習

レッスンのチェックポイント

学んだ内容を復習し、回答へのフィードバックを受けましょう。

0/1
回答済み · 0/1
認証、トークン、安全な資格情報の取り扱い