独自のID プロバイダーを使用したエンドユーザーの認証 authentication
デフォルトでは、アプリ上のすべてのアクションは公開されています。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を名前を付ける必要があります。このバインディングは、別のサービス用に作成されたトークンがアプリに対して再生されるのを防ぐものです。
- アプリの詳細ページを開きます。
- アプリのテストまでスクロールします。
- 設定中の環境で、「URLをコピー」を選択します。
この値を保持する:次の手順でID プロバイダーで必要になります。 コピーしたURLを再入力せずに貼り付けます。 オーディエンスチェックは、パスコンポーネントを含む正確な文字列一致であるため、1文字の違いがあらゆるトークンで検証に失敗します。
ID プロバイダーの設定
正確なステップはプロバイダーによって異なりますが、プロバイダーごとに同じ4つのことが必要です。
- アプリをAPI (リソース)として登録します。 識別子(プロバイダーがトークンの
aud要求に入力する値)を、コピーしたMCP サーバーURLに設定します。 プロバイダーは、このフィールドに様々なラベルを付けます。一般的には 識別子 または オーディエンス です。apiなどの汎用的な値を使用しないでください。識別子はこのアプリに対して一意である必要があります。または、別のサービスに対して発行されたトークンをそのアプリに対して再生できます。 - アクションをゲートするスコープを定義します(例:
orders:readまたはprofile:read)。 有意義な権限ごとに1つのスコープを使用するため、アクションでは必要なものだけを求めます。 - PKCEをサポートします。 LLM プラットフォームは、すべての認証リクエストに
code_challenge_method=S256を含むcode_challengeを送信するので、認証サーバーはS256 PKCEをサポートし、そのメタデータで"code_challenge_methods_supported": ["S256"]をアドバタイズする必要があります。 - LLM プラットフォームがクライアントとして登録することを許可します。 サポートされているLLM プラットフォームは、認証サーバーに対して独自のOAuth クライアントを作成するため、プロバイダーが提供している場合は動的クライアント登録を有効にします。 それ以外の場合は、公開クライアントを手動で作成し、そのクライアント IDを提供します。これは、プラットフォームでのコネクタのセットアップ中にプロバイダーが機密情報のクライアント認証を必要とする場合に限ります。 Claudeのホストされているサーフェス
https://claude.ai/api/mcp/auth_callbackのリダイレクト URIをプラットフォーム ドキュメントに登録します。 一部のプラットフォームでは、ユーザーが作成する各コネクタに対して個別のリダイレクト URIを発行します。そのため、コネクタの設定画面から値を読み取り、最初のサインインの前に登録します。 ChatGPT未登録のリダイレクト URIでは、認証サーバーが認証リクエストを完全に拒否します。
認証を有効にする
-
左側のナビゲーションで「設定」を選択し、「認証」タブを開きます。
-
Workspaceで、ステージまたは 実稼動 を選択します。
-
認証を有効にするをオンにします。
-
コア設定で、次のように入力します。
- Issuer —ID プロバイダーの発行者URL。これは、各トークンの
iss要求に入力する値でもあります。 これは必須であり、HTTPSである必要があり、アプリの認証サーバーとして公開されるので、LLM プラットフォームはユーザーの送信先を検出できます。 アプリごとに1つのID プロバイダーのみがサポートされます。 - スコープがサポートされています – このアプリのアクションに必要なすべてのスコープが許可されます。 ID プロバイダーで定義したスコープをミラーリングします。
- Issuer —ID プロバイダーの発行者URL。これは、各トークンの
-
詳細設定はオプションです。 署名キーが認証サーバーのメタデータで通知されている場所にない場合にのみ JWKS URI を設定します。そうでない場合は、アプリが自動的にそれらを検出します。
-
「保存」を選択します。
各フィールドで使用できる内容については、認証設定を参照してください。
各アクションの認証モードを選択
認証を有効にするを有効にすると、現在 なし に設定されているすべてのアクションが 必須 に変更されます。 アクションごとの設定で、その割り当てを確認し、各アクションに必要なモードを設定します。
必須または オプション に既に設定されているアクションは、既存のモードを維持します。
必須またはオプション アクションの場合は、必要な スコープ を追加します。 すべてのスコープは、既に上記の サポートされているスコープ に表示されている必要があります。そうでない場合、アプリはLLM プラットフォームにアドバタイズしない権限を必要とします。 この不一致が解決されるまで、保存はブロックされます。
サポートされている範囲がこのリストの権限です。 スコープを削除すると、変更を加えるとすぐに、そのスコープが必要なすべてのアクションから削除されるので、最初にスコープを追加してから、アクションに割り当てます。
すべてのアクションに対して認証を要求は、すべてのアクションを 必須 に設定します。 これをクリアすると、すべてのアクションが None に戻ります。
完了したら、保存を選択します。 認証モードとスコープの変更は、アプリレベルの設定とともに保存されます。
1つのアプリ(公開アクション、ゲーテッドアクションなど)でモードを混在させることがサポートされており、ChatGPTは各アクションのモードを個別に適用します。ゲーテッドアクションのみがユーザーにログインを促します。
変更をデプロイ
認証の変更は、このアプリの次回のデプロイに反映されます。 設定した環境にアプリを再び デプロイします。 アプリのデプロイ を参照してください。
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が本当に見つからない場合にのみチャレンジします。 無条件にチャレンジするハンドラーは、ログインしても満たすことができないため、ユーザーは呼び出しごとに再認証を求められます。
IDはサーバーサイドにしておきます。 ウィジェットが必要なものだけをstructuredContentに渡し、アクセストークンをそこに絶対に置かないでください。生成されたハンドラーのカスタマイズ を参照してください。
完全な契約については、 ハンドラー認証APIを参照してください。
保護されたアプリのテスト
既存のプラグインまたはコネクタは、デプロイ後に変更をピックアップします。 ゼロから設定するには:
ChatGPT
新規プラグイン ダイアログで、認証を設定して、アプリのアクションの設定方法と一致させます。
オプション アクションは常に匿名呼び出しを受け付けるので、それを含むアプリは完全にゲートされることはありません。すべてのアクションが オプション に設定されている場合でも、混在を選択します。 未認証の発信者を拒否するのは 必須 のみです。
ダイアログの残りの部分については、ChatGPT プラグインのテスト を参照してください。
Claude
カスタムコネクタを追加し、Connectを選択して、ID プロバイダーが提供するサインインを完了します。 アクションがゲートされるたびに、Claudeがコネクタ全体にゲートを付けます。 クラウドコネクタのテスト を参照してください。
確認
- プラットフォームは、独自のID プロバイダーのサインインページにリダイレクトします。
- 保護されたアクションは、ログイン後にユーザー固有のデータを返します。
- ログアウトすると、保護されたアクションでログインを求められます。
- ChatGPTでは、なしに設定されたアクションは、ログインせずに応答します。 Claudeでは、コネクタ全体がゲートされます。
ログインが開始されない場合、またはトークンが拒否された場合は、 トラブルシューティング を参照してください。
セキュリティガイダンス
- 各行動に必要な範囲を最も広げる。 あらゆる行動において、ひとつの広い範囲を再利用してはいけません。
- ID プロバイダーとLLM プラットフォームのコネクタ設定で、クライアントを秘密にしておきます。 メタデータ、ハンドラーコード、ウィジェット、JavaScript、ソースコントロールなどを決して実行しない。
- トークン要求を外部システムからの入力として扱います。 クエリで使用する前に、
authInfo.extraから読み取ったものを検証します。 - 認証を行います。 有効なトークンは、ユーザーが誰であるかを証明するもので、特定のレコードを表示する可能性があるものではありません。データを返す前に、ハンドラーの所有権を確認してください。
- トークン、完全な要求セット、ユーザーIDはログに記録しないでください。
- 安全なエラーを返します。 アップストリーム ID プロバイダーの応答またはスタックトレースをユーザーに表示しないでください。
- 実稼動環境で認証を有効にする前に、実稼動以外のID プロバイダーのテナントに対して ステージ を設定して検証します。
次の手順
- 認証参照 — フィールド、トークン要件、プラットフォーム動作。
- 生成されたハンドラーをカスタマイズ – 保護されたアップストリーム APIをハンドラーから呼び出します。
- アプリをデプロイ 。