ラベル Auth0 の投稿を表示しています。 すべての投稿を表示
ラベル Auth0 の投稿を表示しています。 すべての投稿を表示

2026年8月5日水曜日

Oracle Backend for Firebaseを組み込んだアプリケーションをAuth0で認証する

先日の記事「Oracle Backend for Firebaseを組み込んだアプリケーションをGoogleアカウントで認証する」では、Googleアカウントでの認証を実装しました。本記事ではAuth0のOpenID Connectによる認証を実装してみます。

Auth0のOpenID Connectによる認証を組み込むアプリケーションとして、以下のLiveLabsを実施して作成したアプリケーションを使用します。
Googleアカウントによるユーザー認証の記事で少し説明していますが、Oracle Backend for Firebase(Fusabase)のGoogleAuthProviderは、OAuthProviderと同じ扱いができるように作成されています。そのため、それぞれのクライアントに記述されているユーザー認証のコードにあるGoogleAuthProviderを、OAuthProvider("プロバイダ名")に置き換えることで、Auth0(OpenID Connect)による認証に変わります。


Auth0のOpenID Connectプロバイダを構成する



最初にリダイレクトURIを確認します。

Oracle Backend for Firebaseのコンソールにサインインし、AuthenticationSocial loginを開きます。

Add new providerOpenID Connectを実行します。


プロバイダをEnableに切り替えます。Enableにすると、リダイレクトURIが表示されます。なぜかCopy URIボタンが効かない(サイトをHTTPで構成しているからかもしれません)ため、表示されているリダイレクトURIを選択して、クリップボードにコピーします。

Client IdおよびClient Secretは、Auth0にアプリケーションを作成することにより得られる値なので現時点では不明です。キャンセルをクリックし、ドロワーを閉じます。


Auth0のコンソールでの作業に移ります。

サイドメニューよりアプリケーションを開き、アプリケーションの作成を実行します。


作成するアプリケーションの名前fusabaseとしました。種類一般的なWebアプリケーションを選択します。

作成をクリックします。


アプリケーションが作成されます。設定タブを開きます。

ドメインクライアントIDクライアントシークレットの値をコピーします。これらの値は、Oracle Backend for FirebaseにAuth0をプロバイダとして作成する際に設定します。


下スクロールし、許可するCallback URLとして先ほどOracle Backend for Firebaseのコンソールより確認したリダイレクトURIを設定します。

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


Oracle Backend for Firebaseのコンソールに戻り、Authenticationを開きます。

Add new providerOpenID Connectを実行します。

作成するプロバイダの名前(Name)auth0とします。ここで設定した名前auth0に接頭辞としてoidc_が付けられたoidc_auth0が、作成されるプロバイダの名前になります。Enableをオフにすれば実質的には同じなのですが、作成したプロバイダを削除する方法が無い(見つけられなかった)、また、名前の変更もできないため、名前は注意して決めることをお勧めします。

Auth0のOpenID Connectの構成URLは、ドメインの値から以下になります。

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

構成ファイルからissuerの値を取り出すために、以下のコマンドを実行します。

curl -s https://[ドメイン]/.well-known/openid-configuration | jq -r .issuer

~ % curl -s https://[ドメイン]/.well-known/openid-configuration | jq -r .issuer

https://[ドメイン]/

~ % 


この値がIssuer (URL)に設定する値になります。Auth0の場合は概ねhttps://[ドメイン]/になります。末尾の/(スラッシュ)が無くてもプロバイダとして作成できますが、認証する際にInvalid Tokenというエラーが発生します。そのため、Issuer (URL)の末尾には必ず / (スラッシュ) を付けるようにします。

Auth0のAuthorization Endpointは以下のコマンドで確認できます。

curl -s https://[ドメイン]/.well-known/openid-configuration | jq -r .authorization_endpoint

 ~ % curl -s https://[ドメイン]/.well-known/openid-configuration | jq -r .authorization_endpoint

https://[ドメイン]/authorize

~ %


現時点(2026年8月5日時点)のOracle Backend for Firebaseでは、Issuer (URL)authorizeを付けたURLが、Authorization Endpointであることを期待しています。Auth0のAuthorization Endpointはその形式ですが、大抵のIdP(Microsoft Entra ID、Okta Integrator、Oracle IAMなど)は異なる形式であるため、ユーザー認証が正しく行われません(Authorization Endpointにアクセスした時点で404 Not Foundが発生する)。これらのIdPを使用するには、今後の対応を待つ必要があります。

App IDには、Auth0に作成したアプリケーションのクライアントIDを、App secretには、クライアントシークレットを設定します。

以上を設定し、Saveを実行します。


以上で、Auth0を使ったOpenID Connectによる認証が有効になりました。

それぞれのアプリケーションにOpenID Connectによる認証を組み込む手順は、Googleアカウント(こちらの記事)と違いはありません。とはいえ、Googleアカウントの手順を読んでOpenID Connectに置き換えるのも分かりにくいので、ほとんど同じですがOpenID Connectによる認証の組み込み手順を以下に記述します。


Web/JavaScriptアプリケーションを認証する



JavaScript SDKのAuthenticationモジュールの説明は、以下に記載されています。

LiveLabsのBuild a Recipe Web App with Oracle Backend for Firebaseを実施して作成されたアプリケーションを元に作業します。

Sign inボタンをクリックすると表示されるパネルのSign inCreate accountの間に、Sign in with OIDCというボタンを追加します。


index.htmlsignInButtonの下に、以下の一行を挿入します。ページに表示されるボタンとして、Sign in with OIDCが追加されます。

<button id="signInWithOIDCButton" class="btn btn-outline" type="button">Sign in with OIDC</button>


scripts/app.jsの先頭にあるimport文を更新します。fusabase/authより追加で、OAuthProvidersignInWithPopupをインポートします。
import {
  GoogleAuthProvider,
  OAuthProvider,
  signInWithPopup,
  createUserWithEmailAndPassword,
  getAuth,
  onAuthStateChanged,
  signInWithEmailAndPassword,
  signOut
} from "fusabase/auth";
ボタンsignInWithOIDCButtonを、オブジェクトelの属性として含めます。

signInButtonの下に、以下の一行を挿入します。

signInWithOIDCButton: document.querySelector("#signInWithOIDCButton"),


ボタンsignInWithOIDCButtonをクリックしたときに実行されるコードを追加します。見つけやすいように、signInButtonのイベントリスナー定義の下の配置します。
  el.signInWithOIDCButton.addEventListener("click", () => {
    runAction("Signed in with OIDC.", async () => {
      // ── Sign in with OIDC ─────────
      const provider = new OAuthProvider("oidc_auth0");
      const userCredential = await signInWithPopup(auth, provider);
      // console.log(userCredential);
    });
  });

以上でアプリケーションの更新は完了です。

RecipeShareのアプリケーションにアクセスし、Sign In with OIDCを実行します。



Auth0のサインイン画面がポップアップします。サインインするアカウント情報を入力します。


Auth0のアプリケーションfusabaseへの接続を受け入れます。


Auth0でのサインインに成功すると、メール・アドレスが表示されます。


以上で、Web/JavaScriptアプリケーションを、Auth0で認証することができました。

Auth0でユーザー認証すると、初回の認証時にOracle Backend for Firebaseにアカウントが作成されます。


すでに異なるプロバイダで同名のアカウントが作成済みの場合、Error signing user through IdPというメッセージが表示され、サインインに失敗します。その場合は作成されているアカウントを削除しておく必要があります。




iOS/Swiftアプリケーションを認証する



iOS SDKのAuthenticationモジュールの説明は、以下に記載されています。

LiveLabsのBuild a Recipe iOS App with Oracle Backend for Firebaseを実施して作成されたアプリケーションを元に作業します。

Services/AuthService.swiftに、Auth0でサインインするファンクションsignInWithOIDCを追加します。ファンクションsignInの下に配置します。
    /// Sign in with OIDC
    func signInWithOIDC() async throws {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            _ = try await FusabaseAuth.auth().signIn(with: OAuthProvider(providerID: "oidc_auth0"))
        } catch {
            errorMessage = error.localizedDescription
            throw error
        }
    }

Views/AuthView.swiftに、追加したファンクションsignInWithOIDCを呼び出すボタンSign In With OIDCを追加します。

AuthView.swiftの末尾に、アクションとしてsignInWithOIDCを追加します。
    // MARK: - Actions

    private func signInWithOIDC() {
        Task {
            do {
                try await authService.signInWithOIDC()
            } catch {
                // AuthService surfaces the message via `errorMessage`; nothing else to do.
            }
        }
    }

アクションsignInWithOIDCを呼び出すボタンを追加します。sign-upとsign-inを切り替えるボタン(表示はリンク)の下に配置します。
            // Sign In With OIDC
            Button(action: signInWithOIDC) {
                HStack {
                    if authService.isLoading {
                        ProgressView()
                            .controlSize(.small)
                            .padding(.trailing, 4)
                    }
                    Text("Sign In with OIDC")
                        .fontWeight(.semibold)
                        .frame(maxWidth: .infinity)
                }
            }
            .buttonStyle(.borderedProminent)
            .controlSize(.large)
            .disabled(authService.isLoading)

以上でアプリケーションの更新は完了です。

RecipeShareのアプリケーションを実行します。Sign In with OIDCのボタンが追加されています。

Sign In with OIDCをクリックします。


Auth0のサインイン画面が表示されます。Auth0のアカウントを入力します。

Auth0のアカウントの構成によると思いますが、色々な方法で本人確認を求められます。


Auth0のアプリケーションfusabaseへの接続を受け入れます。


Auth0のサインインに成功し、登録されているレシピの一覧が表示されます。


以上で、iOS/Swiftアプリケーションを、Auth0で認証することができました。


Android/Javaアプリケーションを認証する



Android SDKのAuthenticationモジュールの説明は、以下に記載されています。

LiveLabsのTitle Build a Recipe Android App with Oracle Backend for Firebaseを実施して作成されたアプリケーションを元に作業します。

Fusabase Android SDKの説明には記載されていませんが、Fusabase Android SDKのAuthenticationモジュールには、startActivityForSignInWithProviderが含まれています。このメソッドを使って、Googleアカウントによるサインインを実装します。

掲載しているほとんどのコードは、Claude Opus 5に生成させています。

AuthRepository.javaに以下の2つのファンクションを追加します。
    /**
     * Sign in with OIDC.
     */
    public void signInWithOIDC(Activity activity) {
        isLoading.setValue(true);
        errorMessage.setValue(null);
        OAuthProvider.Builder builder = OAuthProvider.newBuilder("oidc_auth0");
        OAuthProvider provider = builder.build();
        auth.startActivityForSignInWithProvider(activity, provider)
                .addOnSuccessListener(result -> isLoading.postValue(false))
                .addOnFailureListener(error -> {
                    isLoading.postValue(false);
                    errorMessage.postValue(error.getMessage());
                });
    }
    public void resumePendingSocialLogin() {
        Task<AuthResult> pending = auth.getPendingAuthResult();
        if (pending == null) {
            isLoading.postValue(false);
            return;
        }
        pending.addOnSuccessListener(result -> isLoading.postValue(false))
                .addOnFailureListener(error -> {
                    isLoading.postValue(false);
                    errorMessage.postValue(error.getMessage());
                });
    }

これらのファンクションが使用しているクラスをインポートするように、ファイルの先頭に以下のインポート文を追加します。
/* Sign in with Google */
import android.app.Activity;
import com.oracle.mobile.fusabase.auth.GoogleAuthProvider;
import com.oracle.mobile.fusabase.auth.OAuthProvider;
import com.oracle.mobile.fusabase.task.Task;
import com.oracle.mobile.fusabase.auth.AuthResult;

サインインの画面にボタンSign in with OIDCを追加します。

res/values/strings.xmlに以下の1行を挿入します。ボタンのラベルとなる文字列です。

<string name="auth_button_oidc">Sign in with OIDC</string>


サインインの画面にボタンSign in with OIDCを追加します。

res/layout/fragment_auth.xmlを開き、以下の要素をボタンSign inの下に配置します。
        <com.google.android.material.button.MaterialButton
            android:id="@+id/oidcButton"
            style="@style/Widget.Material3.Button.OutlinedButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/spacing_sm"
            android:text="@string/auth_button_oidc" />

AuthFragment.javaを開き、ボタンのアクション(クリック)とAuthRepository.javaに記載したファンクションの紐付けを行います。

ボタンSign in with OIDC(oidcButton)をクリックしたときに、ファンクションsignInWithOIDCが呼び出されるように、以下のコードを追加します。
        binding.oidcButton.setOnClickListener(v -> {
            binding.errorText.setVisibility(View.GONE);
            App.get().auth().signInWithOIDC(requireActivity());
        });
他のボタンと同様に、ページのロード中はクリックを無効にします。以下の1行を、App.get().auth().getIsLoading().observe内に含めます。

binding.oidcButton.setEnabled(!active);


resumePendingSocialLoginを呼び出すコードを、AuthFragment.javaの末尾に追加します。
    @Override
    public void onResume() {
        super.onResume();
        App.get().auth().resumePendingSocialLogin();
    }

main/AndroidManifest.xmlに記載されているSocialLoginActivityの設定を更新します。

android:launchMode="singleTop"を追加し、android:schemeとして、baasmobileで始まるapp_id(英子文字)を文字列として与えます。以下はandroid:schemeの例です。app_idは、作成したアプリケーションごとに異なります。

baasmobile581fb7467326f5b9e063020012ac0157
        <activity
            android:name="com.oracle.mobile.fusabase.auth.SocialLoginActivity"
            android:exported="true"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="baasmobile581fb7467326f5b9e063020012ac0157" />
            </intent-filter>
        </activity>


Auth0によるユーザー認証の実装については以上で完了です。

Androidシミュレータを使って動作確認をするにあたって、ords_hostに10.0.2.2として仮想ネットワークを設定していると、Auth0によるユーザー認証ができません。コールバック・アドレスはHTTPSで保護されているかlocalhostである必要があります。

そのため、main/fusabase-config.jsonords_hostでのホスト指定を、10.0.2.2からlocalhostに戻します。


AndroidシミュレータからORDSに直接接続する代わりに、adb - Android Debug Bridgeを使ってホスト上のTCPポート8181を、シミュレータから見たlocalhost:8181に割り当てます。

~/Library/Android/sdk/platform-tools/adb reverse tcp:8181 tcp:8181
~/Library/Android/sdk/platform-tools/adb reverse --list

adbへのパスは、Android Studioをインストールした環境によって、異なる可能性があります。

% ~/Library/Android/sdk/platform-tools/adb reverse tcp:8181 tcp:8181

% ~/Library/Android/sdk/platform-tools/adb reverse --list

host-10 tcp:8181 tcp:8181


% 


以上で、すべての設定が完了しました。

RecipeShareのアプリケーションを実行します。Sign in with OIDCのボタンが追加されています。

Sign in with OIDCをクリックします。


Auth0のサインイン画面が表示されます。Auth0のアカウントを入力します。

Auth0のアカウントの構成によると思いますが、色々な方法で本人確認を求められます。


Auth0のアプリケーションfusabaseへの接続を受け入れます。


最終的にAuth0による認証が成功すると、登録されているレシピの一覧が表示されます。


以上で、Android/Javaアプリケーションを、Auth0で認証することができました。

2026年7月7日火曜日

ORDS 26.2のMCPサーバーを構成する - Auth0編

Oracle REST Data Services 26.2より、Streamable HTTPで通信するMCPサーバーが実装されました。ORDSのProduct ManagerのJeff Smithさんが、彼のブログで解説しています。

ORDS: now a streaming HTTP MCP Server for Oracle Database

現時点でこのMCPサーバーが提供するツールは、以下の3つです。

database_listschema_informationsql_run

先ほど紹介したPMのブログに記載されていますが、ORDSをMCPサーバーとして構成するにあたって以下の条件があります。
  • ORDSはスタンドアロンであること。WebLogicやTomcatへのデプロイは不可。
  • データベースのスキーマに直接接続する。APEXやRESTサービスの呼び出しのように、プロキシ接続はしない。
  • スキーマORDS_METADATAをデータベースにインストールしなくてもよい。
  • 認可にOAuth 2.0を使用するため、OAuth 2.0/OIDC対応認可サーバーの構成が必要。
ORDSのMCPサーバーの接続先となるデータベースに対する要件はスキーマとパスワードが分かっていることで、構成作業はありません。どちらかというと、MCPクライアントからMCPサーバー、つまりORDSにStreamable HTTPで接続する際に使用する、ユーザー認証と認可を行なうOAuth 2.0/OIDC対応認可サーバーの構成が主要な作業になります。

ORDS 26.2のMCPサーバーの構成方法について、公式ドキュメントの以下に記載されています。

Oracle REST Data Services, Release 26.2
Installation and Configuration Guide

3 Configuring Model Context Protocol (MCP)

本記事では、概ねJeff Smithさんの記事にそってORDSのMCPサーバーを構成してみます。IdPにはAuth0を使用します。確認作業に使用するMCPクライアントとして、MCPJamの代わりにMCP Inspectorを使います。また、mcp-remoteで認証を扱う代わりにOpenRestryでリバース・プロキシを構成し、MCP InspectorからStreamable HTTPでMCPサーバーに接続します。

作業はMacBook ProのDocker/Colimaの環境で実施します。接続先となるデータベースとして、Oracle AI Database 26ai Freeをコンテナで実行します。

Oracle Database Free

MCPサーバーの接続先として、データベースにサンプル・スキーマHRを準備します。Oracle Databaseのサンプル・スキーマのインストール手順については、記事「アップデートされたサンプル・スキーマのインストール」を参考にしてください。

作業ディレクトリとしてords-mcp2を作成し、そこに移動します。

mkdir  -p ords-mcp2
cd ords-mcp2

% mkdir -p ords-mcp2

% cd ords-mcp2

ords-mcp2 % 


ホストがlocalhost、ポートが1521(デフォルト)、サービス名がfreepdb1のデータベースに、スキーマHRで接続できることが作業の前提になります。

ords-mcp2 % sql hr@localhost/freepdb1


SQLcl: 火 7月 07 10:36:36 2026のリリース26.1 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


パスワード (**********?) ******

接続先:

Oracle AI Database 26ai Free Release 23.26.2.0.0 - Develop, Learn, and Run for Free

Version 23.26.2.0.0


SQL> 


ORDS(MCPサーバー)もコンテナとして実行します。そのため、ORDSの実行に必要なJavaを含んだコンテナ・イメージを作成します。ベース・イメージにOracle No-Fee Terms and Conditionsで配布されている、Java SE Development KItのイメージを使用します。

https://container-registry.oracle.com/ords/ocr/ba/java/jdk-no-fee-term

OAuth2による認可の際に発生する制限やプロトコル上の問題を回避するために、リバース・プロキシを構成します。リバース・プロキシにはOpenRestyを使用します。Nginxを使用する場合は、拡張機能のmore_set_headersを組み込む必要があります。

以下のDockerfileから、ORDSのMCPサーバーのコンテナ・イメージを作成します。

Dockerfileで行っていることは、AIが解説してくれます。確認のためにClaude Opus 4.8にDockerfileを貼り付けて解説してもらいましたが、問題なく解説してくれました。


Dockerfileをダウンロードし、コンテナ・イメージとしてords:26.2-jdk25を作成します。

docker buildx build --platform linux/arm64 --load -t ords:26.2-jdk25 .

ords-mcp2 % docker buildx build --platform linux/arm64 --load -t ords:26.2-jdk25 .


[+] Building 196.3s (15/15) FINISHED                              docker:colima

 => [internal] load build definition from Dockerfile                       0.0s

 => => transferring dockerfile: 4.66kB                                     0.0s

 => [internal] load metadata for container-registry.oracle.com/java/jdk-n  2.6s

 => [internal] load .dockerignore                                          0.0s

 => => transferring context: 2B                                            0.0s

 => [ 1/11] FROM container-registry.oracle.com/java/jdk-no-fee-term:25.0  62.6s

 => => resolve container-registry.oracle.com/java/jdk-no-fee-term:25.0.3-  0.0s

 => => sha256:a87cab8ce0241264ec70ecd357271d16ce9d4b 215.41MB / 215.41MB  61.5s

 => => sha256:849b9039d2ad02b8dc03e66b9b808816d12d8cb8a 16.22kB / 16.22kB  0.4s

 => => sha256:a8a0fb099610f2281c99dee54da3dedcc313b1738 12.25MB / 12.25MB  3.8s

 => => sha256:312cc07da4b871d4fb2e1dc4aa27242f74100ced 92.42MB / 92.42MB  23.5s

 => => extracting sha256:312cc07da4b871d4fb2e1dc4aa27242f74100ced7570c762  0.9s

 => => extracting sha256:a8a0fb099610f2281c99dee54da3dedcc313b17385fa1661  0.1s

 => => extracting sha256:a87cab8ce0241264ec70ecd357271d16ce9d4be5168571d9  1.0s

 => => extracting sha256:849b9039d2ad02b8dc03e66b9b808816d12d8cb8a461238e  0.0s

 => [ 2/11] RUN dnf -y update  && dnf -y install unzip curl sudo epel-re  68.9s

 => [ 3/11] RUN curl -o /etc/yum.repos.d/openresty2.repo https://openrest  0.9s

 => [ 4/11] RUN dnf -y -q install certbot openresty  && dnf clean all  &  16.4s

 => [ 5/11] RUN groupadd -g 54321 oinstall  && useradd -u 54321 -g oinsta  0.1s 

 => [ 6/11] RUN mkdir -p /opt/oracle/ords              /etc/ords/config    0.1s 

 => [ 7/11] RUN cat <<'EOF' > /usr/local/openresty/nginx/conf/nginx.conf   0.1s 

 => [ 8/11] RUN chown -R oracle:oinstall /usr/local/openresty              0.2s 

 => [ 9/11] RUN curl -o /tmp/ords.zip https://download.oracle.com/otn_so  33.5s 

 => [10/11] WORKDIR /home/oracle                                           0.0s 

 => [11/11] RUN cat <<'EOF' > /home/oracle/start.sh && chmod +x /home/ora  0.1s 

 => exporting to image                                                    10.7s 

 => => exporting layers                                                    8.4s 

 => => exporting manifest sha256:91b60d9e3128b910d73f67df4c42fdab5372d981  0.0s 

 => => exporting config sha256:062941d460df163aa6311c885ad93b3155d04028c5  0.0s 

 => => exporting attestation manifest sha256:be2a5ef1192a9827c828f1f33a34  0.0s

 => => exporting manifest list sha256:f821fdf1a4b8dc84e7e89d9dbf762dbf0f7  0.0s

 => => naming to docker.io/library/ords:26.2-jdk25                         0.0s

 => => unpacking to docker.io/library/ords:26.2-jdk25                      2.3s

ords-mcp2 % 


作成したコンテナ・イメージより、MCPサーバーをコンテナords-mcpとして実行します。

ORDSの構成ファイルは、ボリューム/etc/ords/configをローカルのフォルダにマウントして保存します。また、ポート8585をホスト・ポート8585に割り当てます。

構成ファイルを保存するフォルダを作成します。

mkdir ords-config

ords-mcp2 % mkdir ords-config

ords-mcp2 % 


コンテナords-mcpを実行します。

docker run -d --rm --name ords-mcp -p 8585:8585 -v ${PWD}/ords-config:/etc/ords/config ords:26.2-jdk25

リバース・プロキシを介さずORDS MCPサーバーに直結したい場合は、ホストの8585にコンテナ内の8080番ポートを割り当てます。(MCP InspectorとAuth0の組み合わせでは、うまく動作しません。)

docker run -d --rm --name ords-mcp -p 8585:8080 -v ${PWD}/ords-config:/etc/ords/config ords:26.2-jdk25

設定ファイルはすべてホストのディレクトリords-config以下に保存されるため、コンテナを再作成しても設定は維持されます。

ords-mcp2 % docker run -d --rm --name ords-mcp -p 8585:8585 -v ${PWD}/ords-config:/etc/ords/config ords:26.2-jdk25

18a6f514d0469bd8a1e60ec4cad621bcb8d74477fd74abf048d264ecfd72a8da

ords-mcp2 %


以上でORDSのMCPサーバーが起動しました。


Auth0のアプリケーション構成



MCPサーバーを構成する前にIdPを構成する必要があります。

以下よりAuth0での作業に移ります。作業の多くは記事「Role based JWT profileで保護したORDS REST APIにアクセスする - Auth0編」と重なりますが、省略せずに紹介します。

Auth0のダッシュボードにサインインします。

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


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

作成をクリックします。


設定タブを開きます。


基本情報ドメインクライアントIDは、MCPサーバーへのアクセスに使用するため、メモしておきます。クライアント・シークレットを参照することはありません。


基本情報ドメインの値より、以下のORDSのグローバル・プロパティの値が決まります。mcp.security.jwt.profile.issuerについては、ドメインに後続の/(スラッシュ)が付きます。mcp.security.jwt.profile.authorization.server.urlには後続の/(スラッシュ)は付きません。

mcp.security.jwt.profile.issuer: https://ドメイン/
mcp.security.jwt.profile.authorization.server.url: https://ドメイン

mcp.security.jwt.profile.jwk.urlは、https://ドメイン/.well-known/oauth-authorization-serverにアクセスして得られるJSONドキュメントに含まれる、jwks_uriの値です。通常、Auth0では認可サーバーの/.well-known/jwks.jsonに配置されています。

mcp.security.jwt.profile.jwk.url: https://ドメイン/.well-known/jwks.json

アプリケーション設定アプリケーションURLに移動します。

本記事ではMCPサーバーを呼び出すクライアントとして、MCP Inspectorを使用します。

そのため、許可するCallback URLとして、以下を設定します。

http://localhost:6274/oauth/callback
http://localhost:6274/oauth/callback/debug

接続するMCPクライアント(Claude Desktopなど)を追加する場合は、それぞれのコールバックURLを追加します。

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


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


名前ORDSMCP2とします。識別子として、ORDSのMCPサーバーのエンドポイントURLを設定します。今回の作業では、http://localhost:8585/mcpです。

このエンドポイントURLはリバース・プロキシが受け付けるURLです。リバース・プロキシはポート番号を含めてORDSに伝えているため、ORDSもエンドポイントURLをhttp://localhost:8080/mcpではなく、http://localhost:8585/mcpとして認識しています。

この識別子は、ORDSのグローバル・プロパティmcp.security.jwt.profile.audienceの値になります。

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

以上で作成します。


カスタムAPIとしてORDSMCP2が作成されます。設定タブを開きます。


ORDS MCPサーバーは、スコープによるアクセス制御3.5 Configure MCP Databases in Scope Mode)とロールによるアクセス制御3.6 Configure MCP Databases in Role Mode)の2種類のアクセス制御の方法を提供しています。

どちらのアクセス制御でも、デフォルトのスコープ "urn:oracle:dbtools:ords:mcpserver:all" の許可が必要です。そのため、スコープによるアクセス制御では「デフォルトのスコープ+カスタム・スコープ」ロールによるアクセス制御では「デフォルトのスコープ+カスタム・ロール」を許可します。

今回はJeff Smithさんの記事にそって、ロールによるアクセス制御を実装します。

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

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

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

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


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

パーミッションとしてデフォルトのスコープurn:oracle:dbtools:ords:mcpserver:all追加します。説明ORDS MCP Serverと記述しています。


カスタムAPIのORDSMCP2に、パーミッションとしてurn:oracle:dbtools:ords:mcpserver:allが追加されました。


アプリケーションアクセスを開き、アプリケーションORDS MCP2からカスタムAPIのORDSMCP2を呼び出せるように、権限を付与します。

アプリケーションORDS MCP2編集を開きます。


ユーザー委任アクセスのタブを選択します。パーミッションとして表示されているurn:oracle:dbtools:ords:mcpserver:allを選択し、アクセスの付与をクリックします。

アクセスが付与されたら、バッテンキャンセルをクリックしてドロワーを閉じます。


アプリケーションORDS MCP2ユーザー委任アクセスが与えられていることを確認します。


アクセス制御に使用するロールを作成します。

ユーザー管理ロールを開き、ロールを作成をクリックします。



新しいロールの名前ORDS_MCP_HRとします。(Jeff Smithさんの記事ではPOOL.HRですが、ORDSのInstallation and Configuration Guideの例を採用しました)。説明Allow Access to HR Schemaとしています。

以上でロールを作成します。


ロールORDS_MCP_HRが作成されました。


パーミッション・タブを開き、urn:oracle:dbtools:ords:mcpserver:allパーミッションとして追加します。


APIとしてORDSMCP2を選択します。パーミッションとして一覧されたurn:oracle:dbtools:ords:mcpserver:allチェックします。

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


パーミッションurn:oracle:dbtools:ords:mcpserver:allが、ロールORDS_MCP_HRに追加されました。


ロールORDS_MCP_HRユーザーを割り当てます。

ユーザー・タブを開き、ユーザーの追加をクリックします。


ロールORDS_MCP_HRに割り当てるユーザーを検索し、割り当てをクリックします。


ロールORDS_MCP_HRに選択したユーザーが割り当てられます。


ロールによるアクセス制御に必要な、アクセス・トークンにロールを含めるためのカスタム・クレームを作成します。カスタム・ロールの名前はroles2とします。

カスタム・クレームの追加は、アクショントリガーで実施します。設定およびトリガーのコードは、Jeff Smithさんの記事で紹介されています。

アクショントリガーを開き、post-loginを選択します。


アクションの追加をクリックし、初めから構築するを実行します。


名前add-custom-claimsランタイムNode22を選択します。

作成をクリックします。


コード・エディタが開くので、Jeff Smithさんの記事に記載されているコードをそのまま転記します。

namespaceとなるMCPサーバーのエンドポイントURLはhttp://localhost:8585/mcp、カスタム・クレームの名前もroles2としているため問題ありません。
exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'http://localhost:8585/mcp';
  if (event.authorization) {
    api.idToken.setCustomClaim(`roles2`, event.authorization.roles);
    api.accessToken.setCustomClaim(`roles2`, event.authorization.roles);
  }
};
以上でデプロイします。


post-loginトリガーのページに戻り、作成したアクションadd-custom-claims開始完了の間にドラッグ&ドロップします。


アクションadd-custom-claimsを開始と終了の間に配置し、適用をクリックします。


post-loginトリガーが更新されました。


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


ORDS MCPサーバーの構成



ORDSの構成に移ります。

コンテナに接続して、ORDSの構成コマンドを実行します。

docker exec -it ords-mcp bash

ords-mcp2 % docker exec -it ords-mcp bash

[oracle@c68b1bf8aa17 ~]$ 


ORDSのグローバル・プロパティを設定します。[Domain]の部分は、Auth0に作成したアプリケーションORDS MCP2のドメインの値に置き換えます。

ロールによるアクセス制御を行うため、mcp.security.jwt.profile.role.claim.name/roles2を設定しています。
ords --config /etc/ords/config config set --global feature.mcp true
ords --config /etc/ords/config config set --global mcp.security.jwt.profile.issuer https://[Domain]/
ords --config /etc/ords/config config set --global mcp.security.jwt.profile.audience http://localhost:8585/mcp
ords --config /etc/ords/config config set --global mcp.security.jwt.profile.jwk.url https://[Domain]/.well-known/jwks.json
ords --config /etc/ords/config config set --global mcp.security.jwt.profile.authorization.server.url https://[Domain]
ords --config /etc/ords/config config set --global mcp.security.jwt.profile.role.claim.name /roles2
続いて、スキーマHRに接続するコネクション・プールとしてmcp-hrを構成します。ORDS MCPサーバーはコンテナ内で実行されているため、コンテナ外にあるデータベースの接続先としてhost.docker.internalを設定しています。

ロールによるアクセス制御を行うため、mcp.roleORDS_MCP_HRを設定しています。
ords --config /etc/ords/config config --db-pool mcp-hr set db.connectionType basic
ords --config /etc/ords/config config --db-pool mcp-hr set db.hostname host.docker.internal
ords --config /etc/ords/config config --db-pool mcp-hr set db.port 1521
ords --config /etc/ords/config config --db-pool mcp-hr set db.servicename freepdb1
ords --config /etc/ords/config config --db-pool mcp-hr set db.username HR
ords --config /etc/ords/config config --db-pool mcp-hr set db.description "Sample Schema Human Resources"
ords --config /etc/ords/config config --db-pool mcp-hr set mcp.role ORDS_MCP_HR
コネクション・プールmcp-hrがデータベースに接続する際に使用するパスワードを設定します。スキーマHRに設定したパスワードです。

ords --config /etc/ords/config config --db-pool mcp-hr secret db.password

[oracle@c68b1bf8aa17 ~]$ ords --config /etc/ords/config config --db-pool mcp-hr secret db.password


ORDS: Release 26.2 Production on Tue Jul 07 05:44:58 2026


Copyright (c) 2010, 2026, Oracle.


Configuration:

  /etc/ords/config


Enter the database password: ********

Confirm password: ********

The setting named: db.password was set to: ****** in configuration: mcp-hr

[oracle@c68b1bf8aa17 ~]$ 


コンテナから抜けて再起動します。

exit
docker restart ords-mcp

[oracle@c68b1bf8aa17 ~]$ exit

exit

ords-mcp2 % docker restart ords-mcp

ords-mcp

ords-mcp2 % 



MCP Inspectorによる接続確認



MCP Inspectorを起動し、MCPサーバーに接続します。

npx @modelcontextprotocol/inspector

ORDS MCPサーバーに接続するにあたって、以下を設定します。

Transport Type: Streamable HTTP
URL; http://localhost:8585/mcp
Connection Type: Via Proxy
OAuth2 2.0 Flow Client ID: アプリケーションORDS MCP2のクライアントID
Scope: urn:oracle:dbtools:ords:mcpserver:all

以上でConnectをクリックします。


アプリケーションへの接続の許可を求められます。Acceptをクリックします。


MCPサーバーに接続されます。

Toolsタブを開き、List Toolsを実行します。

呼び出し可能なツールとしてdatabase_listschema_informationsql_runがリストされます。


以降はORDS MCPサーバーの使い方になります。

MCPサーバーの使い方は認可サーバーの種類に依存しないので、別の記事でまとめようと思います。

今回の記事は以上になります。