OAuthで実現するAIエージェントの安全な代理実行

広範なアクセス権を持つ共有サービスアカウントを一つ使用することは、エージェントがユーザーとして振る舞う上で誤ったやり方です。どのOAuthフローが適切か、エージェントごとにスコープをどう設定するか、リフレッシュとアクセス権の取り消しをどのように処理するか、そして全てのブランチをテストする方法を学びましょう。

Ashley Innocent

Ashley Innocent

26 8月 2026

OAuthで実現するAIエージェントの安全な代理実行

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

エージェントが顧客のカレンダーを読み取ったり、アカウントからメッセージを送信したり、顧客名でチケットを起票したりする必要があるとします。手っ取り早い方法は、幅広いアクセス権を持つサービスアカウントを1つ持ち、それを通じて行動することです。この場合、すべてのアクションは「インテグレーション」として表示され、どのユーザーが何をトリガーしたかを誰も区別できず、資格情報が1つ漏洩すると、アクセスしているすべてのアカウントが危険にさらされます。

正しい方法は、委任された認証です。ユーザーはエージェントにスコープが限定され、取り消し可能なトークンを付与し、エージェントはそのユーザーとして行動し、監査証跡にはそのユーザーの名前が記録されます。これはOAuth 2.0が構築された目的です。エージェントにとって扱いにくいのは、OAuthがブラウザと「許可」をクリックする人間がいることを前提としているのに対し、エージェントは午前3時にバックグラウンドで実行されるという点です。

このガイドでは、エージェントに適したOAuthフロー、トークンのスコープ設定と保存方法、更新と取り消しへの対処法、実際の環境なしで全体のパスをテストする方法について説明します。キーベース認証と委任認証のどちらを選ぶか迷っている場合は、APIキーとOAuthの比較から始めるのが良いでしょう。

Apidogは、チームが見落としがちな部分、つまりエージェントが本番環境で直面する前に、有効期限切れや取り消しを含むフローのすべての分岐を検証するのに役立ちます。

サービスアカウントか委任アクセスか

2つのモデルは異なる方法で失敗するため、慎重に選択してください。

サービスアカウントは、エージェント自身のIDであり、独自の権限を持ちます。これは、エージェントがあなたのために行う作業、例えば自身のデータベースを読み取ったり、自身の内部サービスを呼び出したり、インフラに対してスケジュールされたジョブを実行したりするのに適しています。エージェントのための最小権限APIキーに関する投稿で説明しているように、スコープを厳密に設定し、定期的に更新してください。

委任アクセスは、エージェントが特定のユーザーとして、そのユーザーの権限のみを行使するものです。データが他人のものである場合には常に必要です。以下の3つの特性が、追加の労力を費やす価値がある理由です。ユーザーは何が許可されたかを確認でき、ユーザーはそれを取り消すことができ、すべての行動はログにそのユーザーのIDを記録します。

避けるべき失敗モードは、組織全体へのアクセス権を持つサービスアカウントを「ユーザーとして」行動するために使用することです。これは機能しますが、単一の漏洩した資格情報が全員を危険にさらし、ユーザーごとの取り消し機能や正直な監査証跡が存在しないことを意味します。

エージェントに適したフロー

OAuth 2.0はいくつかのグラントタイプを定義しており、ここで意味をなすのはごくわずかです。OAuth 2.0の仕様には完全なセットがありますが、ここでは使用するものを紹介します。

PKCE付き承認コード。 ユーザーとして行動するための標準的なフローです。ユーザーはプロバイダーにリダイレクトされ、スコープを承認し、あなたのサービスはコードをトークンと交換します。PKCEは交換を保護し、OAuth 2.0セキュリティに関するベストプラクティスに従い、現在ではすべてのクライアントタイプに推奨されるデフォルトです。承認コードグラントの解説では、その仕組みをステップバイステップで説明しています。

エージェントに特化したポイント:このフローは、人間が接続時に一度だけ実行します。エージェントがこれを実行することはありません。エージェントは、フローによって生成された更新トークンを使用します。この2つの瞬間を設計で分離することで、ほとんどの扱いにくさが解消されます。

クライアントクレデンシャル。 マシン間の通信で、ユーザーは関与しません。サービスアカウントには適切ですが、ユーザーとして行動するには不適切です。なぜなら、同意するユーザーが存在しないからです。

デバイス認証グラント。 ブラウザのないマシン上のエージェント向けです。ユーザーはコードを受け取り、携帯電話で承認します。CLIエージェントやヘッドレス環境で役立ちます。

トークン交換。 RFC 8693により、サービスはトークンをより限定的なものに交換できます。これは、ユーザーのより広範なグラントから派生した、1つのタスクに対して1つのスコープに限定されたトークンをサブエージェントに与える方法であり、元のトークンを渡す必要はありません。マルチエージェントシステムを運用している場合、これはエージェントごとの資格情報を実用的にするメカニズムであり、マルチエージェントハンドオフに関する投稿の境界ルールに適合します。

スコープを狭く、エージェントごとに設定する

スコープは委任アクセスがその価値を発揮する場所であり、ほとんどの実装がアプリが必要とする可能性のあるすべてのものを要求することで怠慢になる場所でもあります。

このエージェントが行うことだけを要求してください。スケジュールエージェントはカレンダーへの書き込み権限のみを必要とし、それ以外のものは必要ありません。メール、連絡先、ファイルは不要です。ユーザーは同意画面を読みます。長いリストは信頼性の問題であり、影響範囲の問題でもあります。OAuth 2スコープに関する解説では、プロバイダーがそれらをどのようにモデル化するかを説明しています。

段階的に要求してください。接続時には最小限のものを要求し、ユーザーがそれを必要とする機能を要求したときに、さらに多くのものを要求します。具体的な要求に紐付けられた同意は、許可しやすく、正当化しやすいです。

各エージェントに独自のトークンを与えてください。リサーチエージェントと経理エージェントの両方が同じユーザーのために行動する場合、1つのトークンを共有するのではなく、異なるスコープを持つ2つのトークンを派生させてください。そうすれば、侵害されたリサーチエージェントが払い戻しを発行することはできず、ログにはどのアージェントが行動したかが記録されます。

デフォルトでは読み取りスコープを優先し、書き込みには明示的な昇格を要求してください。これと、AIエージェントのガードレールに関する投稿で説明しているように、破壊的な呼び出しに対する承認ゲートを組み合わせることで、書き込み可能なトークンがエージェントと間違いの間に立ちはだかる唯一のものではないようにします。

保存、更新、取り消し

トークンは資格情報であるため、資格情報として扱ってください。

保存。 更新トークンは、ユーザーごとにキーを設定して、保存時に暗号化してください。ログに書き込んだり、プロンプトに入れたり、モデルに見せたりしてはなりません。コンテキスト内のトークンは、トレースストア、プロバイダーのログ、そしておそらくサマリーに存在するトークンです。エージェントのツール呼び出しのトレースに関する投稿では、読み取り時ではなく、境界で編集する方法について説明しています。

更新。 アクセストークンは設計上、短命です。エージェント自身がこれを管理すべきではありません。HTTPクライアントの前のトークンマネージャーは、有効期限が近づくと更新し、401で一度呼び出しを再試行します。

class TokenManager:
    def __init__(self, store, provider):
        self.store, self.provider = store, provider

    def access_token(self, user_id, agent_scope):
        rec = self.store.get(user_id, agent_scope)
        if rec.expires_in() > 60:
            return rec.access_token
        fresh = self.provider.refresh(rec.refresh_token, scope=agent_scope)
        self.store.save(user_id, agent_scope, fresh)   # ローテーション: 新しい更新トークンを保存
        return fresh.access_token

2つの詳細が重要です。プロバイダーは、更新トークンをローテーションするケースが増えており、更新ごとに新しいトークンを発行し、古いものを無効にします。そのため、新しいトークンをすぐに永続化しないと、ユーザーは締め出されてしまいます。また、ユーザーごとに更新をシリアル化してください。ローテーションするプロバイダーで2つの並行更新が行われると競合が発生し、一方が失敗します。

取り消し。 ユーザーがアクセスを取り消し、トークンが失効し、管理者がアカウントを削除します。エージェントは401および403を再試行可能ではなく、終了と見なして処理する必要があります。認証失敗の再試行は決して助けにならず、乱用防止策をトリガーする可能性があります。エージェント向けAPIエラー設計に関する投稿のエラーパターンに従い、ユーザーとスコープを特定する明確なメッセージを返して、人間が行動できるようにしてください。

同意の問題

エージェントとOAuthの厄介な部分: 同意には人間が必要なのに、エージェントは無人で実行されます。

接続時と実行時を分けることで、管理しやすくなります。接続時に、人間がブラウザを使って一度承認し、更新トークンを保存します。実行時に、エージェントは人間が関与せずにそのグラントを使用します。これは、ほとんどのスケジュールされたエージェントやバックグラウンドエージェントで機能します。

計画すべき2つの制限があります。グラントは、数か月間使用されなくても、あるいはポリシーによって失効することがあります。失効したグラントを検出し、実行を停止し、ユーザーに通知してください。毎晩静かに失敗するのではなく。そして、同意にはスコープの上限があります。ユーザーが一度も許可しなかったスコープを必要とするエージェントは、勝手に権限を昇格させるのではなく、要求する必要があります。

高リスクなものについては、アクション時にもう一つのゲートを追加してください。トークンはエージェントが行動できることを証明しますが、承認ゲートは行動すべきかどうかを決定します。これらは異なる質問であり、両方とも回答されるべきです。

エージェントがフローに遭遇する前にテストする

認証コードパスは、ほとんどのインテグレーションで最もテストされていない部分です。手動で実行するには、プロバイダーの画面をクリックする必要があるためです。

以下の5つのケースを構築してください。

これらをモックに対して実行してください。Apidogでは、トークンエンドポイントと保護されたエンドポイントを定義し、エラーボディを含む各レスポンスをモックできるため、実際のプロバイダーに触れることなく、すべてのマトリックスを実行できます。本番環境の代わりにモックに対してエージェントを実行するというより広範な習慣と、OAuth 2 APIテストガイドではリクエストレベルの詳細について説明しています。

3つの統合とそれらが必要とするもの

カレンダーアシスタント。 1人のユーザーの空き状況を読み取り、会議を予約します。委任アクセス、2つのスコープ、ブラウザでの接続時同意、その後のバックグラウンド実行。興味深い失敗は取り消しです。ユーザーが統合を切断した場合、夜間実行は、使えなくなったグラントを1週間再試行するのではなく、それに気づいて停止する必要があります。

共有受信トレイ内のサポートエージェント。 チームに属するチケットを処理します。ここでは、IDの問題がより明確になります。チームの共有アカウントとして行動することは、リソースが本当にチームに属しているため擁護できますが、その場合、すべての返信が監査ログで同じに見えます。より良いのは、独自のスコープを持つボットIDと、どの人間が実行をトリガーしたかの記録を組み合わせることです。これにより、エージェントが人間であると偽ることなく、帰属関係を維持できます。

社内運用エージェント。 自身のインフラでサービスを再起動し、ダッシュボードを読み取ります。ユーザーデータも委任もありません。狭いスコープを持つサービスアカウントが正しい答えであり、作業は同意ではなく、ローテーションと影響範囲に費やされます。

区切り線は所有権です。データが、アクセスを取り消したいと合理的に考える可能性のある誰かに属している場合は、委任認証を使用してください。あなた自身に属している場合は、サービスアカウントを使用し、スコープ設定に労力を費やしてください。

帰属に人間を保持する

委任認証は「誰のために」という問いに答えます。「誰の要求で」という問いには答えません。エージェントの作業では、この両方が必要です。トークンはエージェントがユーザーとして行動できることを証明しますが、どの人物が実行を要求したかは記録しません。

その2番目のIDを作業と一緒に保持してください。エージェントが割り当てられたタスクを実行する場合、作業管理レイヤーが自然な場所です。Sharklyのタスクは、作業の責任者を、それを実行するために割り当てられたエージェントまたはクルーとともに記録します。これにより、人間の説明責任とエージェントの実行が、2つの分離された可視な事実として保持されます。Sharklyのドキュメントでは、この分離について詳細に説明しています。どのように保存するにせよ、インシデント後の監査の質問は通常「誰がこれを要求したのか」であり、トークンだけではそれに答えることはできません。

モデルに資格情報を保持させない

エージェントシステムにおけるほとんどの認証インシデントを防ぐ1つのアーキテクチャルールは、モデルがトークンを決して見ないということです。

トークンは、モデルがツールを選択し引数を生成した後、HTTPレイヤーでエグゼキュータによって注入されます。ツールスキーマにはtokenパラメータがなく、プロンプトには資格情報が含まれておらず、モデルが読み取るレスポンスからはAuthorizationヘッダーが除去されています。

これは、モデルの入力がどこを通過するかという点で、通常のエージェントよりもエージェントにとって重要です。コンテキスト内のものは何でも、ハンドオフに要約されたり、トレースに書き込まれたり、エラーメッセージでエコーされたり、エージェントに説明を求めたユーザーに返されたりする可能性があります。これらのパスはどれも敵対的なものではありません。これらはすべて通常の機能であり、資格情報がスコープ内に入った瞬間に情報漏洩になります。

同じルールがユーザーIDにも適用されます。エグゼキュータは、この実行がどのユーザーのために機能するかを知っており、そこからトークンを選択します。モデルにユーザー名を決めさせることは、システム内で最も予測不可能なコンポーネントによって行われる認証決定です。

チェックリスト

委任認証は共有キーよりも手間がかかりますが、エージェントが他人のために行動する際に必要な2つのことを提供します。それは、ユーザーがアクセスを取り消せること、そしてログに誰が何をしたかが記録されることです。Apidogをダウンロードして、エージェントが無人で実行される前に、トークンフローとその失敗ケースを構築してください。

よくある質問

エージェント自身でOAuth同意フローを完了できますか? いいえ、試みるべきではありません。同意には、何を許可するかを決定する人が必要です。通常のブラウザフローを通じて人間が一度承認し、その後エージェントがそのグラントを使用できるようにしてください。

各エージェントは独自のOAuthクライアントを持つべきですか? 製品統合ごとに別々のクライアント、そして通常トークン交換を通じて、その中のエージェントごとに別々のトークンを持つべきです。プロバイダーがクライアントごとのレート制限を適用する場合や、独立した取り消しを行いたい場合に、個別のクライアントが役立ちます。

更新トークンがローテーションされ、新しいトークンを見逃した場合どうなりますか? ユーザーは締め出され、再接続する必要があります。新しい更新トークンは、古いものを消費するのと同じトランザクションで永続化し、2つのワーカーが競合しないように、ユーザーごとに更新をシリアル化してください。

モデルにアクセストークンを見せても安全ですか? いいえ、安全ではありません。トークンはHTTPレイヤーに属し、エグゼキュータによって注入されます。モデルが見るものはすべて、トレース、サマリー、またはレスポンスとして最終的に現れる可能性があります。エージェントのための最小特権APIキーに関する投稿で説明されています。

どのアージェントが何をしたかを監査するにはどうすればよいですか? ユーザーID、エージェント名、使用されたスコープ、およびトークン識別子をすべての呼び出しでログに記録し、トークン自体は決して記録しないでください。エージェントのツール呼び出しのトレースに関する投稿で、レコードの形式について説明しています。

プロバイダーがトークン交換をサポートしていない場合はどうなりますか? プロバイダーが複数のグラントを許可している場合は、エージェントごとに個別のグラントを保存するか、自身のゲートウェイでスコープの絞り込みを強制し、エージェントの呼び出しがネットワークを出る前に許可された操作にフィルタリングされるようにしてください。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる