元にしている記事は以下の2本です。
https://apexugj.blogspot.com/2025/12/protecting-ords-by-role-based-jwt-profile.html
記述が重複しますが、Okta Integratorでの確認作業について記載します。
OktaのAdmin Consoleよりグループを開き、グループを追加します。
グループの名前はORDSUsers、説明は「ORDS REST APIへのアクセスを許可」と記述します。
グループに再度アクセスし、グループ一覧を更新します。
作成したグループORDSUsersを開き、ユーザーを割り当てます。
ユーザーを割り当てをクリックします。
グループORDSUsersにユーザーを割り当てます。
ユーザーの割り当てを完了します。
アプリケーション・メニューのアプリケーションを開き、アプリ統合を作成します。
サインイン方法としてOIDC - OpenID Connectを選択します。OIDCを選択するとアプリケーションタイプの選択が現れます。アプリケーションタイプはシングルページアプリケーションを選択します。
次へ進みます。
アプリ統合名をORDS MCPとします。付与タイプのリフレッシュトークンにチェックを入れます。
サインインリダイレクトURIにMCP InspectorのRedirect URLを設定します。ポート番号6274が使用されている場合は、ポート番号が異なるかもしれません。サインアウトリダイレクトURIは何を設定すべきか不明なので、x をクリックして削除しておきます。
割り当てのアクセス制御として選択されたグループにアクセスを制限を選択し、選択されたグループに先ほど作成したグループORDSUsersを含めます。
以上を設定し保存します。
アプリ統合としてORDS MCPが作成されます。
クライアントIDはMCP InspectorのOAuth 2.0 FlowのClient IDに設定する値です。メモしておきます。
セキュリティのAPIを開き、認証サーバーを追加します。(タブには認可サーバーと書いてあります)
追加する認証サーバーの名前はORDSMCP、オーディエンスはapi://ordsmcp(本来ordsmcpの部分はGUIDなど、世界で一意になる値を割り当てるのが望ましい)とします。説明としてAuthentication Server for ORDS MCPを入力します。
以上で保存します。
追加された認証サーバーの設定タブを開き、メタデータURIを確認します。
このURLで取得できるファイルを、nginxが返す/.well-known/oauth-authorization-serverとして配置します。
URLをブラウザで開き、属性jwks_uriの値をコピーします。
この値はORDS_SECURITY.CREATE_JWT_PROFILEの引数p_jwk_urlの値になります。
また、属性issuerをの値をコピーします。この値はORDS_SECURITY.CREATE_JWT_PROFILEの引数p_issuerの値になります。
メタデータURLの末尾にある.well-known以下を除いた部分が、oauth-protected-resourceのauthorization_serversの値になります。
以上でORDS REST APIの保護に必要な値が集まりました。
クレームタブを開き、クレームを追加します。
追加するクレームの名前はrolesとします。トークンタイプに含めるはアクセス・トークンです。
値タイプにグループを選択し、フィルターは次で始まるでORDSを設定します。このフィルターにより、rolesクレームに先ほど作成したグループORDSUsersが含まれます。
クレームを無効化はチェックせず、含めるはいずれかのスコープを選択します。
以上で作成します。
同様の手順でscopeクレームを追加します。
追加するクレームの名前はscopeとします。トークンタイプに含めるにアクセストークン、値タイプに式を選択し、値として以下を記述します。
String.replace(Arrays.toCsvString(access.scope),","," ")
クレームを無効化はチェックせず、含めるはいずれかのスコープを選択します。
以上で作成します。
rolesクレームとscopeクレームが作成されました。
アクセスポリシーを開き、ポリシーを追加します。
ポリシーの名前はORDS MCPとします。説明に「ORDS MCP」と記述し、次に割り当てるに次のクライアントを選択し、クライアントにORDS MCPを含めます。
以上でポリシーを作成します。
アクセスポリシーとしてORDS MCPが作成されました。
ルールを追加します。
ルール名はDefaultとします。デフォルトの設定は変更せず(最低限コア付与の認証コードがチェックされていれば動くはず)、ルールを作成します。
アクセス・ポリシーORDS MCPとルールDefaultが作成されます。
以上でOktaの設定は完了です。
ロール・ベースJWTプロファイルを設定します。
ORDS_SECURITY.CREATE_JWT_PROFILEを実行します。それぞれの引数には、今まで集めた設定値を割り当てます。
begin
ords_security.delete_jwt_profile;
ords_security.create_jwt_profile(
p_issuer => 'https://integrator-********.okta.com/oauth2/******************'
,p_audience => 'api://ordsmcp'
,p_jwk_url => 'https://integrator-********.okta.com/oauth2/******************/v1/keys'
,p_role_claim_name => '/roles'
);
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]#
cd /usr/share/nginx/html
[root@apex opc]# cd /usr/share/nginx/html
[root@apex html]#
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に記述します。Entra IDでは、このファイルの位置が.well-known以下の.well-known/ords/apexdev/sampleserver/mcpでした。
今回の実装ではサーバーが401 Unauthorizedを返すときにWWW-Authenticateヘッダーを返しません。そのため、oauth-protected-resourceの位置が定まらないのかもしれません。
ファイル.well-known/oauth-protected-resource/ords/apexdev/sampleserver/mcpを作成し、以下を記述します。
{
"resource": "api://ordsmcp",
"authorization_servers": {
["https://integrator-*******.okta.com/oauth2/********************/"]
}
}
authorization_serversの設定で、JSON配列を{}で囲んでJSONオブジェクトにしています。構文的に間違っているように思いますが、こうしないとMCP Inspectorがauthorization_serversを認識しません。メタデータをダウンロードし、.well-known以下に配置します。
curl -OL https://integrator-********.okta.com/oauth2/*******************/.well-known/oauth-authorization-server
mv openid-configuration .well-known/
[root@apex html]# curl -OL https://integrator-*******.okta.com/oauth2/*******************/.well-known/oauth-authorization-server
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2624 0 2624 0 0 6777 0 --:--:-- --:--:-- --:--:-- 6762
[root@apex html]# mv oauth-authorization-server .well-known/
[root@apex html]#
以上で全体の設定が完了しました。
MCP Inspectorを起動します。
npx @modelcontextprotocol/inspector
Transport TypeにStreamable HTTPを選択し、URLにORDSのRESTモジュールとして実装されているサンプルのMCPサーバーのURLを設定します。
https://ホスト名/ords/apexdev/sampleserver/mcp
OAuth 2.0 FlowのClient IDに、Oktaに作成した統合アプリORDS MCPのクライアントIDを設定します。
Connectをクリックし、認証プロセスを開始します。
Oktaのサインイン画面に遷移します。ユーザー名を入力し、次へ進みます。
Okta Verifyのコードを入力し確認します。
パスワードを入力し確認します。
以上でRole based JWT profileで保護したORDS REST APIを、MCP Inspectorでアクセスできました。
Oktaによるユーザー認証では、スコープの指定が不要でした。
以下より、ブラウザ版のChatGPTで、このMCPサーバーをアプリとして作成してみます。ChatGPTに組み込むアプリはリソースとしてHTMLを返す必要があり、このMCPサーバーは要件を満たしてはいませんが、認証の確認はできます。
ChatGPTで認証できるように、統合アプリORDS MCPのサインインリダイレクトURIとして、以下を追加します。
ChatGPTのプランに依存すると思いますが(Plusプランで確認しています)ブラウザ版ChatGPTを開発者モードにすると、設定のアプリとコネクターに高度な設定が表示されます。
アプリを作成するをクリックします。
新しいアプリの名前はMy Oracle Appとします。説明として「Oracleデータベースに接続しSELECT文を実行します」を記述します。
MCPサーバーのURLは、MCP Inspectorに設定したURLと同じです。
https://ホスト名/ords/apexdev/sampleserver/mcp
理解したうえで、続行しますをチェックし、作成するをクリックします。
Oktaの認証プロセスが開始します。サインイン手順はMCP Inspectorと同じなので省略します。
サインインが完了すると、作成したアプリMy Oracle Appが接続します。
ここで使用したMCPサーバーはChatGPTアプリとしての実装は行なっていないため、何かができるわけではありませんが、OAuthで認証できることは確認できました。
Claude Desktopではカスタムコネクタとして追加します。
Claude Desktopで認証できるように、統合アプリORDS MCPのサインインリダイレクトURIとして、以下を追加します。
https://claude.ai/api/mcp/auth_callback
追加したカスタムコネクタMy Oracle Appを連携させます。
Oktaでの認証プロセスが完了すると、連携/連携させるというボタンが設定に変わります。
設定をクリックすると、コネクタとして利用できるツールが確認できます。
そのため、チャットから呼び出すことができました。
完










































