独自の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を読み取り、保護され→アプリをテスト→ます。

これは高度なブランチであり、最初に実行するジャーニーの一部ではありません。 最初のアプリを自動的に作成し、最初にアプリをデプロイ ​します。

仕組み

独自の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署名済みトークンはサポートされていません。 ​ トークン要件を参照してください。
  • 管理者はそのID プロバイダーにアクセスできるので、APIとクライアントを登録できます。
  • 設定している環境にアプリを少なくとも1回デプロイします。 デプロイされたMCP サーバーのURLは、トークンのスコープを設定する必要がある値です。

リソース IDをコピー

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

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

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

この値を保持する:次の手順でID プロバイダーで必要になります。 コピーした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 プラットフォームがクライアントとして登録することを許可します。 サポートされているLLM プラットフォームは、認証サーバーに対して独自のOAuth クライアントを作成するため、プロバイダーが提供している場合は動的クライアント登録を有効にします。 それ以外の場合は、公開クライアントを手動で作成し、そのクライアント IDを提供します。これは、プラットフォームでのコネクタのセットアップ中にプロバイダーが機密情報のクライアント認証を必要とする場合に限ります。 Claudeのホストされているサーフェス https://claude.ai/api/mcp/auth_callbackのリダイレクト URIをプラットフォーム ドキュメントに登録します。 一部のプラットフォームでは、ユーザーが作成する各コネクタに対して個別のリダイレクト URIを発行します。そのため、コネクタの設定画面から値を読み取り、最初のサインインの前に登録します。 ChatGPT未登録のリダイレクト URIでは、認証サーバーが認証リクエストを完全に拒否します。
IMPORTANT
ID プロバイダーのイシュア、JWKS、認証、およびトークン エンドポイントはすべて、パブリック HTTPS経由でアクセスできる必要があります。 LLM プラットフォームとデプロイされたアプリの両方が、プロバイダーから直接メタデータを取得するため、VPNまたはIP プロバイダーの背後にあるID プロバイダーはログインを完了できません。 プロバイダーの手前にファイアウォールやweb アプリケーションファイアウォールがあるのは一般的な原因であり、アプリ自体にアクセスできてもフローが乱れる可能性があります。

認証を有効にする

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

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

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

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

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

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

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

各フィールドで使用できる内容については、認証設定を参照してください。

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

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

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

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

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

必須​または​オプション アクションの場合は、必要な​ スコープ ​を追加します。 すべてのスコープは、既に上記の​ サポートされているスコープ ​に表示されている必要があります。そうでない場合、アプリはLLM プラットフォームにアドバタイズしない権限を必要とします。 この不一致が解決されるまで、保存はブロックされます。

サポートされている範囲​がこのリストの権限です。 スコープを削除すると、変更を加えるとすぐに、そのスコープが必要なすべてのアクションから削除されるので、最初にスコープを追加してから、アクションに割り当てます。

すべてのアクションに対して認証を要求​は、すべてのアクションを​ 必須 ​に設定します。 これをクリアすると、すべてのアクションが​ None ​に戻ります。

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

IMPORTANT
認証を有効にする​を元に戻すと、選択した環境に対するこのアクションごとの設定が破棄されます。すべてのアクションのモードとスコープがクリアされ、記憶されません。 もう一度オンにすると、all-Required​からやり直されます。
NOTE
すべてのアクションを​ なし ​に設定しても、認証は無効になりません。 この状態では呼び出しは拒否されませんが、アプリは引き続き認証サーバーをLLM プラットフォームにアドバタイズするため、クライアントはユーザーに追加アクセスを許可しないサインインを提供できます。 アプリを完全に公開するには、認証を有効にする​をオフにしてデプロイします。

1つのアプリ(公開アクション、ゲーテッドアクションなど)でモードを混在させることがサポートされており、ChatGPTは各アクションのモードを個別に適用します。ゲーテッドアクションのみがユーザーにログインを促します。

IMPORTANT
Claudeは例外です。 アクションごとではなくコネクタごとに認証が適用されるので、アプリ上のアクションが​ 必須 ​または​ オプション ​に設定されている場合、Claudeは、コネクタを使用する前にログインするようユーザーに求めます。これには、なし​に設定されたアクションも含まれます。 Claude人のユーザーに対してアクションを公開するには、別のアプリでホストします。

変更をデプロイ

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

MCP サーバーのURLは変更されないので、既に作成したプラグインやコネクタは引き続き機能します。 ゲートが設定されているため、次回の使用時にログインするようユーザーに求められます。

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

検証済みのIDは、2番目の引数としてハンドラーに到達します。 アクションの認証モードに関係なく、呼び出し元が有効なトークンを送信するたびに存在します。そのため、オプション アクションは、トークンが存在する場合は結果をパーソナライズし、そうでない場合は結果を返すことができます。

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
  };
};

トークンを自分で検証する必要はありません。 必須 アクションの場合、ランタイムは、リストされたスコープを含む有効なトークンを欠くすべての呼び出しをブロックするため、ハンドラーは承認済みの呼び出し元に対してのみ実行されます。 オプション アクションなど、ゲートに依存せずに権限で分岐する場合は、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
ChatGPTに、この方法で発生したログインでは、追加の権限を付与するのではなく、コネクタを再接続するようにユーザーに求められます。 Claudeでは、ユーザーはアクションが実行される前にサインインするので、アクションで発生させる必要はありません。

IDはサーバーサイドにしておきます。 ウィジェットが必要なものだけをstructuredContentに渡し、アクセストークンをそこに絶対に置かないでください。生成されたハンドラーのカスタマイズ ​を参照してください。

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

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

既存のプラグインまたはコネクタは、デプロイ後に変更をピックアップします。 ゼロから設定するには:

ChatGPT

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

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

ChatGPT — プラグインの認証モードを選択

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

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

Claude

カスタムコネクタを追加し、Connect​を選択して、ID プロバイダーが提供するサインインを完了します。 アクションがゲートされるたびに、Claudeがコネクタ全体にゲートを付けます。 ​ クラウドコネクタのテスト ​を参照してください。

確認

  • プラットフォームは、独自のID プロバイダーのサインインページにリダイレクトします。
  • 保護されたアクションは、ログイン後にユーザー固有のデータを返します。
  • ログアウトすると、保護されたアクションでログインを求められます。
  • ChatGPTでは、なし​に設定されたアクションは、ログインせずに応答します。 Claudeでは、コネクタ全体がゲートされます。

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

セキュリティガイダンス

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

次の手順

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