独自のID プロバイダーでエンドユーザーを認証する authentication

IMPORTANT
Adobe LLM Appsは現在Betaにいます。
ここに示す機能、ワークフロー、UIは、必ずしも製品の最終状態を表すものではありません。 Betaに参加するには、llm-apps-beta@adobe.comに電子メールを送信します。

デフォルトでは、アプリ内のすべてのアクションは公開されています。 MCP サーバーのURLを持つLLM プラットフォームは、これらのアクションを呼び出すことができ、ハンドラーはエンドユーザーを識別できません。

アクションで、どのエンドユーザーが要求しているのか(注文、使用権限、アカウントの詳細など)を確認する必要がある場合は、認証をオンにします。 LLM プラットフォームは、your ID プロバイダー(IdP)でユーザーに署名し、結果として得られるアクセストークンを呼び出しごとに送信し、ハンドラーは検証済みのIDを受信します。

このガイドでは、 ID プロバイダーを接続し、ログインが必要なアクションを選択する方法について説明します。 ハンドラーで検証済みのIDを使用して、アプリをデプロイし、サインインと保護されたアクションをテストします。

認証の設定は高度なタスクです。 ​ インフラストラクチャの設定、​ アクションの作成、​ アプリのデプロイ ​を最初に実行します。

仕組み

独自のID プロバイダーを利用できます。 デプロイされたアプリは、OAuth 2.1 リソースサーバー​のみです。認証サーバーが発行したトークンを検証します。 トークンは発行されず、Adobeはクライアント IDまたはクライアント秘密鍵を格納しません。

┌── Your identity provider ───────────────────────────────────────────────┐
│  Authorization server — you own it                                      │
│  Issues access tokens, holds the user directory, defines the scopes     │
└─────────────────────────────────────────────────────────────────────────┘
        ▲  2  user signs in, platform gets an access token
        │                                    │
        │  1  platform discovers your        │  3  every tools/call carries
        │     authorization server from      │     Authorization: Bearer <token>
        │     your app's metadata            ▼
┌── LLM platform (ChatGPT, Claude, …) ────────────────────────────────────┐
└─────────────────────────────────────────────────────────────────────────┘
                                             │
                                             ▼
┌── Your LLM App on Adobe I/O Runtime ────────────────────────────────────┐
│  Resource server — verifies the token's signature, issuer, audience,    │
│  and expiry, then enforces the auth mode you set for each action        │
│                                                                         │
│  Your handler reads the verified identity from its second argument      │
└─────────────────────────────────────────────────────────────────────────┘

環境​ ごとに認証 ​を設定します。 ステージ​と​ 実稼動 ​には、独立した設定が含まれています。 実稼動環境​で認証を有効にする前に、開発IdP テナントに対する設定を確認してください。

始める前に

  • 非対称アルゴリズムで署名された​JWT アクセストークンを発行するOAuth 2.1またはOpenID Connect ID プロバイダー。 不透明なトークンとHMAC署名済みトークンはサポートされていません。 ​ トークン要件を参照してください。
  • APIとクライアントを登録するためのID プロバイダーへの管理者アクセス権。
  • 設定している環境にアプリを少なくとも1回デプロイします。 デプロイされたMCP サーバーのURLは、トークンのスコープを設定する必要がある値です。

リソース IDをコピー

アプリの​ リソース識別子 ​はMCP サーバーのURLです。 アプリに対してID プロバイダーが発行するすべてのアクセストークンには、そのURLをオーディエンスとして正確に名前を付ける必要があります。 このオーディエンスバインディングは、別のサービスに対して発行されたトークンの使用を防ぎます。

  1. アプリの詳細ページを開きます。
  2. アプリのテスト​までスクロールします。
  3. 設定中の環境で、「URLをコピー」を選択します。

​ アプリの詳細 – ステージング MCP サーバーのURLをコピー

次の手順で、ID プロバイダー設定のコピーしたMCP サーバーのURLを保持します。 URLを再入力せずに貼り付けます。 オーディエンスチェックには、パスを含む正確な文字列一致が必要です。 1文字の違いがあると、すべてのトークンの検証が失敗します。

NOTE
各環境には独自のMCP サーバーURL、つまり独自のオーディエンスがあります。 ステージ​と​ 実稼動 ​を別々に設定します。

ID プロバイダーの設定

手順はプロバイダーによって異なります。 次の4つの項目を設定します。

  1. アプリをAPI (リソース)として登録します。 識別子(プロバイダーがトークンのaud要求に入力する値)を、コピーされたMCP サーバーURLに設定します。 プロバイダーは通常、このフィールドに​ 識別子 ​または​ オーディエンス ​というラベルを付けます。 別のサービスに対して発行されたトークンの使用を防ぐには、apiなどの一般的な値ではなく、アプリに固有の識別子を使用します。
  2. アクションを保護するスコープ​を定義します(例:orders:readまたはprofile:read)。 意味のある権限ごとに1つの範囲を使用して、各アクションが必要なアクセスのみを要求するようにします。
  3. PKCEをサポートします。 LLM プラットフォームは、すべての認証リクエストにcode_challenge_method=S256を含むcode_challengeを送信するので、認証サーバーはS256 PKCEをサポートし、そのメタデータで"code_challenge_methods_supported": ["S256"]をアドバタイズする必要があります。
  4. LLM プラットフォームがOAuth クライアントを識別する方法を選択します。 プロバイダーがプラットフォームの要件、動的クライアント登録(DCR)、または事前登録済みのOAuth クライアントをサポートしている場合は、クライアント ID メタデータ ドキュメント(CIMD)を使用します。 選択したメソッドが必要な場合にのみ、クライアント IDとシークレットを指定します。 Claudeのホストされたサーフェス https://claude.ai/api/mcp/auth_callbackについて、プラットフォームによって文書化または表示された正確なリダイレクト URIを登録します。 ChatGPTは、プロバイダーの広告付き機能に応じて、安定したコールバックまたはコネクタ固有のコールバックを使用する可能性があるので、推測ではなく、表示されたURIをコピーします。 現在のChatGPT認証ドキュメント ​および​ クラウド認証ドキュメント ​を参照してください。
IMPORTANT
ID プロバイダーのイシュア、JWKS、認証、およびトークン エンドポイントはすべて、パブリック HTTPS経由でアクセスできる必要があります。 LLM プラットフォームとデプロイされたアプリの両方が、プロバイダーから直接メタデータを取得します。 これらのリクエストをブロックするVPN、IP 許可リスト、ファイアウォール、またはweb アプリケーションファイアウォールは、アプリ自体に到達できたままであっても、ログインを防ぎます。

認証を有効にする

  1. 左側のナビゲーションで「設定」を選択し、「認証」タブを開きます。

  2. Workspace​で、ステージ​または​ 実稼動 ​を選択します。

  3. 認証を有効にする​をオンにします。

  4. コア設定​で、次のように入力します。

    • Issuer —ID プロバイダーのHTTPS発行者URL。これは、各トークンのiss要求に入力される値でもあります。 プラットフォームはこのURLを必要とし、イシュアをLLM クライアント発見用のアプリの認証サーバーとして公開します。 各アプリは1つのID プロバイダーをサポートしています。
    • スコープがサポートされています – このアプリのアクションに必要なすべてのスコープが許可されます。 ID プロバイダーで定義したスコープをミラーリングします。
  5. 詳細設定​はオプションです。 署名キーが認証サーバーのメタデータで通知されている場所にない場合にのみ​ JWKS URI ​を設定します。そうでない場合は、アプリが自動的にそれらを検出します。

  6. 「保存」を選択します。

認証 – 認証を有効にし、コア設定を完了します

フィールドの要件については、認証設定を参照してください。

各アクションの認証モードを選択

認証を有効にする​を有効にすると、現在​ なし ​に設定されているすべてのアクションが​ 必須 ​に変更されます。 アクションごとの設定​で、その割り当てを確認し、各アクションに必要なモードを設定します。

モード
動作
なし
パブリック: 発信者にはトークンは必要ありません。
必須
保護: 発信者には、リストされているすべてのスコープを含む有効なトークンが必要です。 ランタイムは、未認証の呼び出し元にサインインを依頼します。
オプション
匿名で呼び出すことができますが、アクションはログインをサポートしていることを宣伝します。 ハンドラーは、呼び出しごとに、一般的な結果を提供するか、パーソナライズされた結果にログインするようにユーザーに依頼するかを決定します。

認証 – アクションごとに認証モードとスコープを設定します

必須​または​ オプション ​に既に設定されているアクションは、既存のモードを維持します。

必須​または​オプション アクションの場合は、必要な​ スコープ ​を追加します。 すべてのスコープは既に​ サポートされているスコープ ​に表示されている必要があるため、アプリは必要な各権限をLLM プラットフォームに通知します。 範囲の不一致が解決されるまで、プラットフォームは保存をブロックします。

サポートされている​ 範囲 ​は、使用可能な範囲を制御します。 そのリストからスコープを削除すると、スコープを必要とするすべてのアクションからスコープがすぐに削除されます。 アクションにスコープを割り当てる前に、各スコープをリストに追加します。

すべてのアクションに対して認証を必要とする​を選択すると、なし​のアクションが​ 必須 ​に変更されますが、既に​ オプション ​に設定されているアクションは保持されます。 すべてのアクションに対してログインを要求するには、残りの​ オプション ​行を個別に​ 必須 ​に変更します。 チェックボックスをオフにすると、すべてのアクションが​ None ​に戻ります。

完了したら、保存​を選択します。 認証モードとスコープの変更は、アプリレベルの設定とともに保存されます。

IMPORTANT
認証を有効にする​をオフにすると、選択した環境のすべてのアクションの認証モードとスコープがクリアされます。 プラットフォームはこれらの設定を保持しません。 認証を再度有効にすると、すべてのアクションが​ 必須 ​に設定されます。
NOTE
すべてのアクションを​ なし ​に設定しても、認証は無効になりません。 この状態でログインする必要はありませんが、アプリは引き続き認証サーバーをLLM プラットフォームにアドバタイズします。 顧客は、追加のアクセス権を付与しないログインを提供できます。 アプリを完全に公開するには、認証を有効にする​をオフにしてデプロイします。

ChatGPTは、1つのアプリ内で混合認証モードをサポートし、各アクションのモードを個別に適用します。 公開アクションではログインを求めるメッセージは表示されません。保護されたアクションでは、必要に応じてプロンプトが表示されます。

Claudeは、遅延認証​を通じて混在アプリもサポートしています。 コネクタのセットアップ中に​ 必要に応じてログイン ​を選択すると、パブリックアクションは匿名で使用でき、必須 アクションが呼び出されたときにプラットフォームがログインを要求します。 アクションがすべて​ 必須 ​のアプリは、使用する前にログインする必要があります。 必須アクションとサインインを要求するオプションのハンドラーの違いについては、LLM プラットフォームの動作を参照してください。

NOTE
現在のランタイムは、バージョン 1.1.5に対して検証されたこの混合認証動作をサポートしています。 古いデプロイ済みアプリでは、ランタイムの更新と再デプロイメントが必要になる場合があります。 一部のUI ビルドでは、Claudeがコネクタ全体の認証を必要としているという従来の警告が表示されます。 デプロイされたランタイムを確認し、警告に頼るのではなく、必要に応じてClaudeの現在の​サインイン オプションを使用します。

変更をデプロイ

認証の変更は、このアプリの次回のデプロイに反映されます。 設定した環境にアプリを再び デプロイします。 ​ アプリのデプロイ ​を参照してください。

MCP サーバーのURLは変更されません。 接続のメタデータを更新し、認証設定がアプリの新しい設定と一致することを確認します。 プラットフォームの認証方法が変更されたときに、接続を再接続または再作成する必要がある場合があります。

ハンドラーでIDを読み取る

確認されたIDは、アクションの認証モードに関係なく、発信者が有効なトークンを送信するたびに、2番目の引数としてハンドラーに到達します。 オプション アクションは、そのIDを使用して、利用可能な場合に結果をパーソナライズし、そうでない場合は匿名の結果を返すことができます。

getAuthenticatedUserを使用して、サインイン ユーザーを読み取ります:

const { getAuthenticatedUser } = require('@adobe/llm-apps-runtime');

module.exports = async ({ orderId }, extra) => {
  const userId = getAuthenticatedUser(extra);

  if (!userId) {
    return { content: [{ type: 'text', text: 'Sign in to see your orders.' }] };
  }

  const order = await fetchOrderForUser(userId, orderId);

  return {
    content: [{ type: 'text', text: `Order ${order.id} is ${order.status}.` }],
    structuredContent: order
  };
};

ランタイムはトークンを検証します。 Required アクションの場合、リストされたスコープを持つ有効なトークンを欠くすべての呼び出しをブロックします。 ハンドラーは、許可された呼び出し元に対してのみ実行されます。 hasScopeを使用して、権限に基づいてハンドラーの動作を選択します(例:オプション アクション)。

会話中にログインをリクエストするには、ハンドラーからextra.challengeAuth()を返します。 ヘルパーは、オプション​のアクションでのみ使用できます。

module.exports = async ({ signIn }, extra) => {
  if (signIn && !extra.authInfo) {
    return extra.challengeAuth({
      error: 'invalid_token',
      errorDescription: 'Sign in to see member pricing.'
    });
  }

  return {
    content: [{
      type: 'text',
      text: extra.authInfo ? await memberDeals() : await publicDeals()
    }]
  };
};

この例のsignInなどの明示的な入力パラメーターを使用して、認証を要求するタイミングを決定します。 その決定をユーザーの言葉遣いから推測しないでください。

報告された条件に一致するようにerrorを設定します。 呼び出し元に有効なセッションがなく、上記の例のようにログインが必要な場合は、invalid_tokenを使用します。 呼び出し元がサインインしているが、トークンに必要な範囲が不足している場合はinsufficient_scopeを使用します。 各LLM プラットフォームは、プロンプトの文言とエラーコードへの対応方法を選択します。 条件を正確に記述したコードを送信します。

この例では!extra.authInfo チェックで示されているように、必要なIDが見つからない場合にのみ認証を要求します。 ログインしても、無条件の課題は解決されません。ハンドラーは、呼び出しごとに認証を再度要求します。

NOTE
extra.challengeAuth()は、ChatGPTに対するツール結果チャレンジを返します。 代わりに、Claudeは、ハンドラーを実行する前にHTTP認証チャレンジを必要とします。 サポートされているプラットフォーム間でログインが必要な操作の場合は、必須 アクションを使用します。 必要に応じて、パブリックエクスペリエンス用に個別の​None アクションを保持します。

IDはサーバーサイドにしておきます。 ウィジェットに必要なデータのみをstructuredContentに渡します。 structuredContentにアクセストークンを絶対に含めないでください。 生成ハンドラーのカスタマイズ ​を参照してください。

完全な契約については、​ ハンドラー認証APIを参照してください。

保護されたアプリのテスト

既存のプラグインまたはコネクタは、デプロイメント後に更新された設定を使用します。 新しい接続を作成するには、プラットフォームの手順に従います。

ChatGPT

新規プラグイン ダイアログで、認証​を設定して、アプリのアクションの設定方法と一致させます。

アプリのアクション
選択
すべて​ なし ​に設定
認証なし
すべて​ 必須 ​に設定されています
OAuth
その他の組み合わせ
混在

オプション アクションは常に匿名呼び出しを受け付けるので、それを含むアプリは完全にゲートされることはありません。すべてのアクションが​ オプション ​に設定されている場合でも、混在​を選択します。 未認証の発信者を拒否するのは​ 必須 ​のみです。

ダイアログの残りの部分については、ChatGPT プラグインのテスト ​を参照してください。

Claude

カスタムコネクタを追加し、認証設定を確認します。 公開と保護が混在するアプリの場合は、必要に応じて​ログインを選択します。 コネクタを使用する前にログインをリクエストするには、今すぐログイン​を選択します。 ダイアログはアカウントまたは組織によって異なります。Claude コネクタのテスト ​を参照してください。

確認

  • プラットフォームは、独自のID プロバイダーのサインインページにリダイレクトします。
  • 保護されたアクションは、ログイン後にユーザー固有のデータを返します。
  • ログアウトすると、保護されたアクションでログインを求められます。
  • 混在アプリでは、None​に設定されたアクションは、ログインせずに応答します。 Claudeで、必要に応じて​ログインして公開アクションを確認します。
  • ログイン後、保護されたアクションを再試行し、ランタイムが期待される権限を適用することを確認します。

ログインが開始されない場合、またはトークンが拒否された場合は、​ トラブルシューティング ​を参照してください。

セキュリティガイダンス

  • 各行動に必要な範囲を最も広げる。 あらゆる行動において、ひとつの広い範囲を再利用してはいけません。
  • ID プロバイダーとLLM プラットフォームのコネクタ設定で、クライアントを秘密にしておきます。 メタデータ、ハンドラーコード、ウィジェット、JavaScript、ソースコントロールなどを決して実行しない。
  • トークン要求を外部システムからの入力として扱います。 クエリでこれらの値を使用する前に、authInfo.extraの値を検証します。
  • 認証を行います。 有効なトークンは、特定のレコードを読み取る権限ではなく、ユーザーのIDを証明します。 データを返す前に、ハンドラーの所有権を確認してください。
  • トークン、完全な要求セット、ユーザーIDはログに記録しないでください。
  • 安全なエラーを返します。 アップストリーム ID プロバイダーの応答またはスタックトレースをユーザーに表示しないでください。
  • 実稼動環境​で認証を有効にする前に、実稼動以外のID プロバイダーのテナントに対して​ ステージ ​を設定して検証します。

次の手順

recommendation-more-help
llm-apps-help-main-toc