Skip to Content

OAuth2認証・DCRガイド

Custom Remote MCPサーバーにOAuth 2.0認証を適用する方法を説明します。Dynamic Client Registration(DCR)に対応すると、ユーザーはURLを入力するだけで自動的に認証を完了できます。

概要

質問回答
Custom MCPでOAuth2をサポートしていますか?✅ 完全にサポートしています。
各ユーザーが個別に認証できますか?✅ はい、トークンはユーザーごとに管理されます。
DCRは必須ですか?❌ いいえ、オプションです。なければClient ID/Secretを手動で入力します。
DCRがあると何が良いですか?自動クライアント登録により、ユーザー体験が大幅に向上します。

OAuth2認証方式

AIPはMCPサーバーのURLを入力すると自動的にOAuthメタデータを検出し、以下の3つの方式のいずれかで動作します。

OAuthWithDCR(自動クライアント登録)

  • 条件: MCPサーバーがDCRスペックに対応
  • ユーザー操作: URLを入力するだけ
  • AIP処理: 自動でクライアント登録を実行
  • 結果: OAuthポップアップが自動表示

OAuth(手動Client ID/Secret入力)

  • 条件: MCPサーバーがDCR非対応
  • ユーザー操作: Client ID / Secretを直接入力
  • AIP処理: 入力された資格情報でOAuth処理
  • 結果: OAuthポップアップ表示

NoAuth(認証なし)

  • 条件: OAuthメタデータDiscoveryで利用可能なメタデータを取得できない
  • ユーザー操作: なし
  • AIP処理: この設定ではOAuthフローを開始しない
  • 結果: OAuthポップアップなし

MCPサーバーURLを入力した直後に、AIPが自動的にOAuth Discoveryを実行して認証方式を決定します。

DCRとは

Dynamic Client Registration(DCR)RFC 7591 標準プロトコルで、OAuth2クライアント(AIP)がAuthorization Serverに自動登録してClient IDとSecretを取得する方式です。

DCRなしの場合(従来方式)

  1. ユーザーが該当サービスでOAuth Appを手動で作成します。
  2. Client ID / Secretを取得します。
  3. AIPに手動で入力します。
  4. OAuthポップアップが進行します。

DCRありの場合

  1. ユーザーがAIPにMCP Server URLを入力します。
  2. AIPが自動的にサーバーにClientを登録します。
  3. Client ID / Secretが自動的に発行されます。
  4. OAuthポップアップが進行します(ユーザー入力不要)。

DCR対応有無の判定基準

AIPはMCPサーバーのAuthorization Server Metadataに registration_endpoint フィールドがあるかを確認します:

// Example response from /.well-known/oauth-authorization-server { "issuer": "https://mcp.example.com", "authorization_endpoint": "https://mcp.example.com/oauth/authorize", "token_endpoint": "https://mcp.example.com/oauth/token", "registration_endpoint": "https://mcp.example.com/oauth/register" // DCR supported if present }

AIPのOAuth自動検出フロー

MCPサーバーURLを入力すると、AIPバックエンドが以下の順序で自動検出を行います:

  1. MCPサーバーにPOSTリクエスト送信
    • 401応答 + WWW-Authenticateヘッダー → Protected Resource Metadata URL抽出
    • 401以外 → /.well-known/oauth-protected-resourceを確認
  2. Protected Resource Metadataからauthorization_serversを抽出
  3. Authorization Server Metadata(ASM)取得 — 優先順位順
    • RFC 8414: /.well-known/oauth-authorization-server/{path}
    • OIDC (path insertion): /.well-known/openid-configuration/{path}
    • OIDC (path appending): /{path}/.well-known/openid-configuration
  4. 認証方式の決定
    • ASM取得失敗 → NoAuth(メタデータfallback)
    • ASMにregistration_endpointあり → OAuthWithDCR
    • ASMにregistration_endpointなし → OAuth(手動入力)

Discovery処理でOAuthメタデータを解決できない場合、メタデータ判定はNoAuthにfallbackし、OAuthポップアップは表示されません。一方、DCR実行時の失敗は別扱いで、AIPはDCR未対応エラーを返し、UIは手動Client ID / Secret入力に切り替わります。

設定ガイド

DCR対応サーバーの連携(例:Linear)

URL入力

Integrations → All Integrations → カスタムMCP連携設定 をクリックし、MCP Server URLを入力します。

自動認証

AIPが自動的にDCRを実行し、OAuthポップアップが表示されます。サービスアカウントでログインすると連携が完了します。

トークン管理

各ユーザーが独立して認証され、トークンはユーザーごとに個別管理されます。

DCR非対応サーバーの連携(例:Salesforce)

AIPでMCPを追加

  1. Integrations → All Integrations → カスタムMCP連携設定 でMCP Server URLを入力します。
  2. Install をクリックすると、Client ID / Secret入力ダイアログが表示されます。ダイアログにはOAuth Callback URL(コピーボタン付き)と必要なScope一覧も表示されます。

OAuth Appの作成

MCPサーバーの管理コンソールでOAuth Appを作成します:

  1. OAuth Settingsを有効化します。
  2. Callback URLを入力します。AIPのClient ID / Secret入力ダイアログからOAuth Callback URLをコピーして登録します。
  3. 必要なScopeを選択します。
  4. Client IDとClient Secretをメモします。

OAuthログイン

  1. AIPのClient ID / Secret入力ダイアログに戻り、前の手順でメモしたClient ID / Secretを入力します。
  2. OAuthポップアップでサービスアカウントにログインします。ログインが完了すると、AIPがサービスから認証トークンを受信し、連携が完了します。内部処理の詳細はOAuth2内部処理フローを参照してください。

Salesforce Custom Domain環境では、AIPが自動的に再ログインを要求してcross-org OAuthエラーを防止します。問題が続く場合は、別のブラウザプロファイルの使用をお試しください。

社内ネットワークサーバーの連携(Edge Tunnel必要)

MCPサーバーが社内ネットワークまたはlocalhostで稼働している場合:

  1. AIP Desktop CLIでEdge Tunnelを起動します。
  2. Custom MCP設定時に 「Use Edge Tunnel」 オプションをチェックします。
  3. 以降のOAuth Discoveryおよび認証フローは同様に進行します。

詳細はEdge Tunnelドキュメントを参照してください。

DCR非対応時の困難

DCRをサポートしないMCPサーバーを連携する際に発生する問題点です:

  • 手動クライアント準備が必要 — 連携を設定する主体がOAuth Appを作成または登録し、Client ID / Secretを提供する必要があります。
  • Scope設定ミス — AIPが必要なScopeを案内しますが、ユーザーがOAuth Appに手動で追加する必要があります。漏れがあるとツール呼び出しが失敗します。
  • Client Secretのセキュリティ — SecretをAIPに直接入力する構造のため、管理負担が増加します。
  • 運用の複雑さ — Client ID/Secretの期限切れや再発行時に再入力が必要です。
  • 高い導入障壁 — 技術に不慣れなユーザーにとってOAuth App作成は難しい作業です。

DCR実装ガイド(MCPサーバー開発者向け)

MCPサーバーでDCRをサポートするには、メタデータに公開される2つのエンドポイントと、メタデータが指すregistration_endpointの実装の両方が必要です。

1. Protected Resource Metadata

GET /.well-known/oauth-protected-resource Response: { "resource": "https://mcp.example.com", "authorization_servers": ["https://auth.example.com"] }

2. Authorization Server Metadata

registration_endpoint が含まれていることで、AIPがDCRとして認識します。

GET /.well-known/oauth-authorization-server Response: { "issuer": "https://auth.example.com", "authorization_endpoint": "https://auth.example.com/authorize", "token_endpoint": "https://auth.example.com/token", "registration_endpoint": "https://auth.example.com/register", "scopes_supported": ["read", "write"], "response_types_supported": ["code"], "grant_types_supported": ["authorization_code", "refresh_token"], "code_challenge_methods_supported": ["S256"], "token_endpoint_auth_methods_supported": ["client_secret_basic"] }

registration_endpoint がない場合、AIPは自動的にOAuth(手動入力)方式にfallbackします。 code_challenge_methods_supportedS256を含めると、AIPが自動的にPKCEを適用してセキュリティが強化されます。含めることを推奨します。

3. Client Registration Endpoint

registration_endpointは、AIPが自動クライアント登録時に直接呼び出すPOSTエンドポイントです。RFC 7591形式のクライアントメタデータを受け取り、client_idclient_secretなどの登録結果を返す必要があります。

POST /oauth/register Content-Type: application/json Request: { "client_name": "Custom MCP Client of AI Platform", "redirect_uris": ["https://{aip-domain}/integration/oauth/callback"], "grant_types": ["authorization_code", "refresh_token"], "scope": "read write", "token_endpoint_auth_method": "client_secret_basic" } Response (201 Created): { "client_id": "aip_123456789", "client_secret": "replace-with-secure-secret", "client_id_issued_at": 1712236800, "client_secret_expires_at": 0, "redirect_uris": ["https://{aip-domain}/integration/oauth/callback"], "grant_types": ["authorization_code", "refresh_token"], "token_endpoint_auth_method": "client_secret_basic" }

実装例(Node.js)

const crypto = require('crypto'); // Protected Resource Metadata app.get('/.well-known/oauth-protected-resource', (req, res) => { res.json({ resource: 'https://mcp.example.com', authorization_servers: ['https://auth.example.com'] }); }); // Authorization Server Metadata app.get('/.well-known/oauth-authorization-server', (req, res) => { res.json({ issuer: 'https://auth.example.com', authorization_endpoint: 'https://auth.example.com/authorize', token_endpoint: 'https://auth.example.com/token', registration_endpoint: 'https://auth.example.com/register', scopes_supported: ['read', 'write', 'admin'], response_types_supported: ['code'], code_challenge_methods_supported: ['S256'], grant_types_supported: ['authorization_code', 'refresh_token'], token_endpoint_auth_methods_supported: ['client_secret_basic'] }); }); // Client Registration Endpoint app.post('/oauth/register', (req, res) => { res.status(201).json({ client_id: `aip_${crypto.randomBytes(16).toString('hex')}`, client_secret: crypto.randomBytes(32).toString('hex'), client_id_issued_at: Math.floor(Date.now() / 1000), client_secret_expires_at: 0, redirect_uris: req.body.redirect_uris ?? [], grant_types: req.body.grant_types ?? ['authorization_code', 'refresh_token'], token_endpoint_auth_method: req.body.token_endpoint_auth_method ?? 'client_secret_basic' }); });

実装例(Python)

from flask import Flask, jsonify, request import time import secrets app = Flask(__name__) @app.route('/.well-known/oauth-protected-resource') def oauth_resource_metadata(): return jsonify({ 'resource': 'https://mcp.example.com', 'authorization_servers': ['https://auth.example.com'] }) @app.route('/.well-known/oauth-authorization-server') def oauth_authorization_server(): return jsonify({ 'issuer': 'https://auth.example.com', 'authorization_endpoint': 'https://auth.example.com/authorize', 'token_endpoint': 'https://auth.example.com/token', 'registration_endpoint': 'https://auth.example.com/register', 'scopes_supported': ['read', 'write', 'admin'], 'response_types_supported': ['code'], 'code_challenge_methods_supported': ['S256'], 'grant_types_supported': ['authorization_code', 'refresh_token'], 'token_endpoint_auth_methods_supported': ['client_secret_basic'] }) @app.route('/oauth/register', methods=['POST']) def oauth_register(): payload = request.get_json(silent=True) or {} return jsonify({ 'client_id': f'aip_{secrets.token_hex(16)}', 'client_secret': secrets.token_hex(32), 'client_id_issued_at': int(time.time()), 'client_secret_expires_at': 0, 'redirect_uris': payload.get('redirect_uris', []), 'grant_types': payload.get('grant_types', ['authorization_code', 'refresh_token']), 'token_endpoint_auth_method': payload.get('token_endpoint_auth_method', 'client_secret_basic') }), 201

例示は文書説明用の最小実装です。実際の運用環境では、登録されたクライアントを永続化し、許可されたリダイレクトURIの検証とclient secretの保護ポリシーを実装する必要があります。

トラブルシューティング

OAuthポップアップが表示されない場合

  1. OAuthメタデータDiscoveryが正常に動作するか確認します。
    curl https://mcp.example.com/.well-known/oauth-protected-resource
    PRM応答に authorization_servers が含まれる場合は、その値が指すAuthorization Server Metadataにもアクセスできることを確認してください。
  2. AIPからMCPサーバーURLへのHTTPアクセスが可能か確認します(ファイアウォール等)。
  3. 社内ネットワークサーバーの場合、「Use Edge Tunnel」 オプションをチェックしたか確認します。
  4. MCP Server URLが正確か確認します(例:https://host/sse)。
  5. MCPサーバーが標準OAuth2 Authorization Code Flowに対応しているか確認します。

認証失敗エラー

  • Client ID / Secretが正確か確認します。
  • OAuth AppのリダイレクトURIホワイトリストにAIPのOAuthコールバックURLを追加します。
  • サーバーログでOAuthエンドポイントのエラーメッセージを確認します。

ユーザー別認証が動作しない場合

  • 別のユーザーアカウントで再度ログインします。
  • MCPサーバーでユーザーごとに異なるトークンが発行されているか確認します。
Last updated on