2025年12月18日木曜日

Role based JWT profileで保護したORDS REST APIにMCP Inspectorでアクセスする - Oracle IAM編

Oracle REST Data ServicesのRESTモジュールをRole based JWT profileで保護し、そのREST APIにMCP Inspectorでアクセスしてみます。

以下の記事に記載されている手順を実施済みとします。

Oracle IAMのOIDC認証にてAPEXアプリとそれから呼び出すORDSのREST APIを認証する
https://apexugj.blogspot.com/2024/06/verification-of-oauth-create-jwt-profile-oracle-iam.html

Oracle IAMの統合アプリにカスタム・クレームを追加しRole based JWT profileによる保護を確認する
https://apexugj.blogspot.com/2025/12/protecting-ords-by-role-based-jwt-profile-with-oracle-iam.html

本記事では、以下の作業が完了していることを前提とします。
  • 発行者(issuer)をデフォルトのhttps://identity.oraclecloud.com/としています。
  • 署名証明書へのアクセスクライアント・アクセスの構成有効にしています。
  • カスタム・クレームiam_groupsを作成しています。
記述が重複しますが、Oracle IAMでの確認作業について記載します。

Defaultドメインのユーザー管理を開き、ORDSでロールとして扱うグループを作成します。


作成するグループの名前ORDSUsers説明は「ORDS REST APIへのアクセスを許可」と記述します。

グループに含めるユーザーチェックし、作成を実行します。


グループORDSUsersが作成されます。


ユーザータブを開き、グループ作成時にチェックしたユーザーが含まれていることを確認します。


グループの作成は以上で完了です。

Defaultドメインの統合アプリケーションを開き、 アプリケーションの追加をクリックします。


モバイル・アプリケーションを選択し、ワークフローの起動をクリックします。


追加するモバイル・アプリケーションの名前ORDS MCPとします。画面下部にある、認証と認可権限付与を認可として実施オンにします。このアプリケーションに割り当てられたユーザーおよびグループのみがサインインできるようになります。

送信をクリックします。


アプリケーションORDS MCPが作成されます。


OAuth構成タブを開きます。

一般情報クライアントIDは、MCP InspectorのOAuth 2.0 FlowClient IDに設定する値になります。接続時に必要になるため、メモしておきます。

OAuth構成の編集をクリックします。


認可許可される権限付与タイプに含まれる、リフレッシュ・トークン認可コードチェックします。

MCP InspectorのリダイレクトURLはHTTPなので、HTTPS以外のURLを許可オンにします。

リダイレクトURLとして、以下の3つを設定します。

http://localhost:6274/oauth/callback
https://chatgpt.com/connector_platform_oauth_redirect
https://claude.ai/api/mcp/auth_callback

以上を設定し、送信します。


アプリケーションをアクティブ化します。

アクション・メニューのアクティブ化を実行します。


アプリケーションがアクティブ化されたら、ユーザータブを開き、このアプリケーションにサインインできるユーザーの割当てを実施します。


アプリケーションに割り当てるユーザーを選択し、割当てをクリックします。


以上で、Oracle IAMにモバイル・アプリケーションORDS MCPが作成できました。


ORDS REST APIの保護とアクセスに必要な設定を集めます。

発行者はデフォルト値としているので、ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際に、引数p_issuerに与える値はhttps://identity.oraclecloud.com/になります。

Defaultドメインの詳細に記載されているドメインURLが、ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際に、引数p_audienceに与える値になります。また、この値はoauth-protected-resourceのresource属性に設定する値になります。


以下のURLで取得できる内容を、nginxが返す/.well-known/openid-configurationとして配置します。

https://ドメインURL/.well-known/openid-configuration

上記のURLにブラウザよりアクセスし、属性jwks_uriの値を取得します。この値は、ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際に、引数p_jwk_urlに与える値になります。


oauth-protected-resourceauthorization_serversとして設定する値は、ドメインURLになります。ドメインURLの末尾に/(スラッシュ)を加えます。

ORDS REST APIの保護とアクセスに必要な設定は以上になります。

ロール・ベースJWTプロファイルを設定します。

ORDS_SECURITY.CREATE_JWT_PROFILEを実行します。それぞれの引数には、今まで集めた設定値を割り当てます。引数p_role_claim_nameには、以前の記事で作成している/iam_groupsを指定します。
begin
    ords_security.delete_jwt_profile;
    ords_security.create_jwt_profile(
        p_issuer => 'https://identity.oraclecloud.com/'
        ,p_audience => 'ドメインURL'
        ,p_jwk_url => 'ドメインURL/admin/v1/SigningCert/jwk'
        ,p_role_claim_name => '/iam_groups'
    );
end;
/

ビューUSER_ORDS_JWT_PROFILEを検索し、設定した内容を確認します。

select issuer,audience,jwk_url,role_claim_name from user_ords_jwt_profile


以下のスクリプトを実行し、Oracle REST Data Servicesに権限oracle.example.mcpを作成(すでに存在する場合は再定義)します。ロールとしてORDSUsersを作成し、RESTモジュールsampleserverを保護します。
declare
    l_roles    owa.vc_arr;
    l_modules  owa.vc_arr;
    l_patterns owa.vc_arr;
begin
    ords.create_role(
        p_role_name => 'ORDSUsers'
    );
    l_modules(1) := 'sampleserver';
    l_roles(1)   := 'ORDSUsers';
    ords.define_privilege(
        p_privilege_name => 'oracle.example.mcp',
        p_label          => 'Priviledge for MCP',
        p_roles          => l_roles,
        p_modules        => l_modules,
        p_patterns       => l_patterns    -- no assignment
    );
end;
/

nginxを実行しているインスタンスに接続し、/.well-known/以下を設定します。

rootユーザーで作業します。

sudo -s

[opc@apex ~]$ sudo -s

[root@apex opc]# 


nginxのドキュメント・ルートに移動します。

cd /usr/share/nginx/html

[root@apex opc]# cd /usr/share/nginx/html

[root@apex html]# 


ディレクトリ.well-knownがすでに存在すれば名称を変えて保存し、新たに.well-knownを作成します。

mv .well-known well-known.bak
mkdir .well-known


[root@apex html]# mv .well-known well-known.bak

[root@apex html]# mkdir .well-known

[root@apex html]# 


リモートMCPサーバーのアクセスパスが/ords/apexdev/sampleserver/mcpなので、oauth-protected-resourceとして記述する内容は.well-known以下の.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpに記述します。

ファイル.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpを作成し、以下を記述します。
{
  "resource": "ドメインURL",
  "authorization_servers": {
    ["ドメインURL/"]
  }
}
authorization_serversの設定で、JSON配列を{}で囲んでJSONオブジェクトにしています。構文的に間違っているように思いますが、こうしないとMCP Inspectorがauthorization_serversを認識しません。

メタデータをダウンロードし、.well-known以下に配置します。

curl -OL ドメインURL/.well-known/openid-configuration
mv openid-configuration .well-known/


[root@apex html]# curl -OL https://**********.identity.oraclecloud.com:443/.well-known/openid-configuration

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100  3166  100  3166    0     0  36355      0 --:--:-- --:--:-- --:--:-- 36390

[root@apex html]# mv openid-configuration .well-known/

[root@apex html]# 


以上で全体の設定が完了しました。

MCP Inspectorを起動します。

npx @modelcontextprotocol/inspector

Transport TypeStreamable HTTPを選択し、URLにORDSのRESTモジュールとして実装されているサンプルのMCPサーバーのURLを設定します。

https://ホスト名/ords/apexdev/sampleserver/mcp

OAuth 2.0 FlowClient IDに、Oracle IAMに作成した統合アプリケーションORDS MCPクライアントIDを設定します。

Connectをクリックし、認証プロセスを開始します。


Oracle IAMのサインインの画面に遷移します。


ユーザー認証に成功しました。


以上でRole based JWT profileで保護したORDS REST APIを、MCP Inspectorでアクセスできました。

記事「Role based JWT profileで保護したORDS REST APIにMCP Inspectorでアクセスする - Auth0編」と同じ作業を行い、ChatGPTのアプリ、およびClaude Desktopのカスタムコネクタを作成してみました。

ブラウザ版のChatGPTでは、nginxが返す/.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpの内容を以下に変更する必要がありました。authorization_serversはオブジェクトとして与えます。
{
  "resource": "ドメインURL",
  "authorization_servers": {
    ["ドメインURL/"]
  },
  "scopes_supported": ["files:read", "files:write"]
}
上記の設定で、ChatGPTアプリとして作成できました。

Claude Desktop向けでは、/.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpとして以下を記述しています。authorization_serversは配列として与えます。
{
  "resource": "ドメインURL",
  "authorization_servers": 
    ["ドメインURL/"]
  ,
  "scopes_supported": ["files:read", "files:write"]
}
また、Claude Desktopは/.well-known/openid-configurationを探さなかったので、/.well-known/oauth-authorization-serverとして配置する必要がありました。

上記の設定で、Claude Desktopのカスタムコネクタとして作成できました。

クライアントとIdPの組み合わせに依存して、oauth-protected-resourceauthorization_serversがオブジェクトを受け付けたり、配列を受け付けたりするのは謎ですが、とにかく接続はできました。

今回の記事は以上です。

Role based JWT profileで保護したORDS REST APIにMCP Inspectorでアクセスする - Auth0編

Oracle REST Data ServicesのRESTモジュールをRole based JWT profileで保護し、そのREST APIにMCP Inspectorでアクセスしてみます。

元にしている記事は以下の2本です。

Auth0のOIDC認証にてAPEXアプリとそれから呼び出すORDSのREST APIを認証する
https://apexugj.blogspot.com/2025/12/verification-of-oauth-create-jwt-profile-auth0.html

Oracle REST Data ServicesのRole based JWT profileによる保護を確認する
https://apexugj.blogspot.com/2025/12/protecting-ords-by-role-based-jwt-profile.html
記述が重複しますが、Auth0での確認作業について記載します。

Auth0 Dashboardにサインインします。

アプリケーション・メニューのアプリケーションを開き、アプリケーションを作成します。


名前ORDS MCPとし、アプリケーションの種類としてシングルページWebアプリケーションを選択します。

作成をクリックします。


設定タブを開きます。


基本情報ドメインクライアントIDは、Oracle REST Data Servicesの保護とアクセスに使用します。メモしておきます。


基本情報ドメインの値より、以下の設定値が決まります。

ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際の引数p_issuerの値は、ドメインの値をhttps:///で囲んだ、https://ドメイン/になります。

oauth-protected-resourceに設定するauthorization_serversは、ドメインの値をhttps:///で囲んだ、https://ドメイン/になります。

nginxからアクセスする/.well-known/oauth-authorization-serverは、以下のURLで取得するファイルとして作成します。

https://ドメイン/.well-known/oauth-authorization-server

上記のURLにアクセスし、属性jwks_uriの値を取得します。


属性jwks_uriの値は、ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際の引数p_jwk_urlの値になります。

基本情報クライアントIDは、MCP InspectorのOAuth 2.0 FlowClient IDに設定します。

Redirect URLアプリケーションURI許可するCallback URLに設定するため、コピーしておきます。


Auth0 Dashboardに戻り、アプリケーション設定アプリケーションのURLまでスクロールします。

許可するCallback URLに、MCP InspectorおよびChatGPTとClaude DesktopのコールバックURLを、カンマ区切りで設定します。

http://localhost:6274/oauth/callback,https://chatgpt.com/connector_platform_oauth_redirect,https://claude.ai/api/mcp/auth_callback

以上で設定を保存します。


アプリケーションAPIを開き、APIの作成を実行します。


名前ORDSMCPとします。識別子としてapi://ordsmcp/を設定します。本来は世界で一意になるようにapi://GUID/または保護するAPIのエンドポイントURLを設定します。

識別子として指定した値は、ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際の引数p_audienceの値になります。また、oauth-protected-resourceに含まれるresource属性の値になります。

JSON Web Token (JWT) プロファイルおよびJSON Web Token (JWT) の署名アルゴリズムはデフォルトをそのまま採用します。

以上で作成します。


カスタムAPIとしてORDSMCPが作成されます。


ORDSのREST APIをロール・ベースJWTプロファイルで保護するため、RBACを有効にします。

設定をスクロールし、RBACの設定に移動します。

RBACを有効化オンアクセストークンに権限を追加するオンに変更します。

必ずしも必要ではありませんが、アクセスの設定ユーザー同意のスキップを許可するオフにしています。

以上で変更を保存します。


パーミッションタブを開きます。

パーミッションとしてORDSUsersを作成します。これをORDSではロール名と解釈するように、JWTプロファイルを作成します。説明に「ORDS REST APIの呼び出し」と記述し、追加をクリックします。


カスタムAPIのORDSMCPに、パーミッションとしてORDSUsersが追加されました。


ユーザー管理メニューのユーザーを開き、アプリケーションORDS MCPにサインインするユーザーに、権限を割り当てます。


APIとしてORDSMCPを選択し、パーミッションORDSUsersチェックします。

以上でパーミッションを追加します。


ユーザーの設定画面を開き、パーミッションタブより、パーミッションとしてORDSUsersが追加されていることを確認します。


MCPに限らないと思いますが、Auth0による認証ではアクセス・トークンのリクエスト時にaudienceが指定されていないと、アクセス・トークンとして暗号化されたトークンが返されます。

MCP InspectorのGitHubのIssue#566の議論が参考になります。

ワークアラウンドとして、Auth0にデフォルトのオーディエンスを設定します。

Auth0 Dashboardの設定の、一般設定タブを開きます。


APIの認可設定までスクロールし、デフォルトのオーディエンスとしてapi://ordsmcp/を設定します。

設定を保存します。


謝辞:デフォルト・オーディエンスの設定はVictor Roninさんの以下の記事が参考になりました。
Configuring an MCP Server with Auth0 as the Authorization Server

以上でAuth0の設定は完了です。

ロール・ベースJWTプロファイルを設定します。

ORDS_SECURITY.CREATE_JWT_PROFILEを実行します。それぞれの引数には、今まで集めた設定値を割り当てます。引数p_role_claim_nameには/permissionsを指定します。
begin
    ords_security.delete_jwt_profile;
    ords_security.create_jwt_profile(
        p_issuer => 'https://ドメイン/'
        ,p_audience => 'api://ordsmcp/'
        ,p_jwk_url => 'https://ドメイン/.well-known/jwks.json'
        ,p_role_claim_name => '/permissions'
    );
end;
/

ビューUSER_ORDS_JWT_PROFILEを検索し、設定した内容を確認します。

select issuer,audience,jwk_url,role_claim_name from user_ords_jwt_profile


以下のスクリプトを実行し、Oracle REST Data Servicesに権限oracle.example.mcpを作成(すでに存在する場合は再定義)します。ロールとしてORDSUsersを作成し、RESTモジュールsampleserverを保護します。
declare
    l_roles    owa.vc_arr;
    l_modules  owa.vc_arr;
    l_patterns owa.vc_arr;
begin
    ords.create_role(
        p_role_name => 'ORDSUsers'
    );
    l_modules(1) := 'sampleserver';
    l_roles(1)   := 'ORDSUsers';
    ords.define_privilege(
        p_privilege_name => 'oracle.example.mcp',
        p_label          => 'Priviledge for MCP',
        p_roles          => l_roles,
        p_modules        => l_modules,
        p_patterns       => l_patterns    -- no assignment
    );
end;
/

nginxを実行しているインスタンスに接続し、/.well-known/以下を設定します。

rootユーザーで作業します。

sudo -s

[opc@apex ~]$ sudo -s

[root@apex opc]# 


nginxのドキュメント・ルートに移動します。

cd /usr/share/nginx/html

[root@apex opc]# cd /usr/share/nginx/html

[root@apex html]# 


ディレクトリ.well-knownがすでに存在すれば名称を変えて保存し、新たに.well-knownを作成します。

mv .well-known well-known.bak
mkdir .well-known

[root@apex html]# mv .well-known well-known.bak

[root@apex html]# mkdir .well-known

[root@apex html]# 


リモートMCPサーバーのアクセスパスが/ords/apexdev/sampleserver/mcpなので、oauth-protected-resourceとして記述する内容は.well-known以下の.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpに記述します。

ファイル.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpを作成し、以下を記述します。
{
  "resource": "api://ordsmcp/",
  "authorization_servers": {
    ["https://ドメイン/"]
  }
}
メタデータをダウンロードし、.well-known以下に配置します。

curl -OL https://ドメイン/.well-known/oauth-authorization-server
mv 
oauth-authorization-server .well-known/

[root@apex html]# curl -OL https://dev-:************.us.auth0.com/.well-known/oauth-authorization-server

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100  1960    0  1960    0     0   8622      0 --:--:-- --:--:-- --:--:--  8634

[root@apex html]# mv oauth-authorization-server .well-known/

[root@apex html]# 


以上で全体の設定が完了しました。

MCP Inspectorを起動します。

npx @modelcontextprotocol/inspector

Transport TypeStreamable HTTPを選択し、URLにORDSのRESTモジュールとして実装されているサンプルのMCPサーバーのURLを設定します。

https://ホスト名/ords/apexdev/sampleserver/mcp

OAuth 2.0 FlowClient IDに、Auth0に作成したアプリケーションORDS MCPクライアントIDを設定します。

Connectをクリックし、認証プロセスを開始します。


Auth0のサインインの画面に遷移します。


ユーザー認証に成功しました。


以上でRole based JWT profileで保護したORDS REST APIを、MCP Inspectorでアクセスできました。

以下より、ブラウザ版のChatGPTで、このMCPサーバーをアプリとして作成してみます。ChatGPTに組み込むアプリはリソースとしてHTMLを返す必要があり、このMCPサーバーは要件を満たしてはいませんが、認証の確認はできます。

ChatGPTからの接続を確認する前に、nginxが返す/.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpの内容を以下に変更します。ChatGPTはauthorization_serversの指定は配列であることを期待しています(仕様としてはこれが正しい)。また、scopes_supportedの指定が必要です。scopes_supportedについては、MCPサーバーにアクセスしたときにステータス401とともに返すWWW-Authenticateレスポンス・ヘッダーに、要求するスコープが含まれていることが期待されているようです。参照リンク
{
  "resource": "api://ordsmcp/",
  "authorization_servers": [
    "https://ドメイン/"
  ],
  "scopes_supported": ["files:read", "files:write"]
}
ChatGPTのプランに依存すると思いますが(Plusプランで確認しています)ブラウザ版ChatGPTを開発者モードにすると、設定アプリ高度な設定が表示されます。

アプリを作成するをクリックします。


新しいアプリの名前My Oracle Appとします。説明として「Oracleデータベースに接続しSELECT文を実行します」を記述します。

MCPサーバーのURLは、MCP Inspectorに設定したURLと同じです。

https://ホスト名/ords/apexdev/sampleserver/mcp

認証OAuthを選択し、OAuthクライアントIDに、Auth0に作成したアプリケーションORDS MCPのクライアントIDを設定します。

理解したうえで、続行しますチェックし、作成するをクリックします。


Auth0の認証プロセスが開始します。サインイン手順はMCP Inspectorと同じなので省略します。

サインインが完了すると、作成したアプリMy Oracle Appが接続します。

アクションとしてツールのget_schemaやrun_sqlが見えているので、OAuthによる認証は成功しています。


ここで使用したMCPサーバーはChatGPTアプリとしての実装は行なっていないため、何かができるわけではありませんが、OAuthで認証できることは確認できました。

Claude Desktopではカスタムコネクタとして追加します。ChatGPTと同じ設定でカスタムコネクタを追加します。


Claude Desktopでは、MCP Inspectorではなく、ChatGPTで使用した/.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpで接続できました。

追加したカスタムコネクタMy Oracle App連携させます。


Auth0での認証プロセスが完了すると、連携/連携させるというボタンが設定に変わります。


設定をクリックすると、コネクタとして利用できるツールが確認できます。


Claude DesktopのカスタムコネクタはChatGPTとは異なり、リモートMCPサーバーとして利用できるようです。

そのため、チャットから呼び出すことができました。


今回の記事は以上です。