2024年6月26日水曜日

Oracle IAMのOIDC認証にてAPEXアプリとそれから呼び出すORDSのREST APIを認証する

Oracle IAMのOpenID Connect認証でOracle APEXのアプリケーションを認証し、その際に発行されたアクセス・トークンを使用してOracle REST Data ServicesのREST APIを認証します。Oracle REST Data ServicesではJWTプロファイルを設定することにより、Oracle IAMが発行したアクセス・トークンで認証します。

Oracle CloudのAlways Freeのプランを使用します。

検証作業に、以下のAPEXアプリケーションORDS JWT Testをインポートして使用します。
https://github.com/ujnak/apexapps/blob/master/exports/ords-jwt-test.zip

上記のAPEXアプリケーションをインストールすると、サポートするオブジェクトとして、APEXアプリケーション以外にいくつかのオブジェクトが作成されます。

データベース・オブジェクトとして、ファンクションDUMP_SIGNON_RESPONSEPARSE_JWT(23ai以上)、MLEモジュールMOD_CORE_JSMOD_JWT_DECODEMOD_PARSE_JWT(23ai以上)、MLE環境JWTENV(23ai以上)が作成されます。

RESTサービスとしてprintが作成されます。権限myordsappが作成され、作成されたRESTサービスprintは権限myordsappにより保護されます。

Web資格証明としてOracle IAM JWT Testが作成されます。


APEXアプリケーションのインポートにより、APEX側で必要な作業のほとんどが実施されます。

以下より、Oracle IAMにAPEXアプリケーションを登録する手順を説明します。

Oracle Cloudのコンソールにサインインし、アイデンティティとセキュリティドメインを開きます。


ドメイン・タイプFreeのドメインDefaultに、アプリケーションを作成します。Defaultドメインはルート・コンパートメントに存在します。


詳細タブにドメインURLがあります。これをコピーして保存します。


Oracle APEXの認証スキームを作成する際に設定する、OpenID Connectプロバイダ検出URLは、このドメインURL/.well-known/openid-configurationを付加したURLになります。

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

この検出URLにブラウザでアクセスします。

取得されたJSONドキュメントにORDS_SECURITY.CREATE_JWT_PROFILEの引数p_jwk_urlの値となる、JSON Web Keyの取得URLがjwks_uri属性として含まれます。

jwks_uri属性の値は後で使用するため、コピーして保存します。


jwks_uriのURLは通常、ドメインURLに/admin/v1/SigningCert/jwkを付加したURLになります。

JSON Web Keyの取得URL: https://ドメインURL/admin/v1/SigningCert/jwk

ブラウザから、このURLにアクセスできるかどうか確認します。設定によっては、以下のようにアクセスが許可されていないというエラーが発生します。

{"schemas":["urn:ietf:params:scim:api:messages:2.0:Error","urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error"],"detail":"許可されていないアクセスのため、操作は失敗しました。","status":"401","urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error":{"messageId":"error.common.exception.unauthorizedAccess"}}

Oracle IAMでは、JSON Web Keyを取得するURLはデフォルトで保護されています。その保護を解除します。

設定タブを開きます。

署名証明書へのアクセスクライアント・アクセスの構成無効になっているはずです。これを有効にします。

ドメイン設定の編集をクリックします。


署名証明書へのアクセスクライアント・アクセスの構成オンに変更し、変更を保存します。


署名証明書へのアクセスクライアント・アクセスの構成有効に変わります。


再度、JSON Web Keyにアクセスし、鍵情報を含むJSONドキュメントが取得できることを確認します。

次にOAuth2の発行者(issuer)を確認します。

セキュリティタブを開き、OAuth設定の編集をクリックします。


OAuth設定の編集をクリックするとドロワーが開きます。

この中に発行者という設定があります。この設定はオプションで、発行者はデフォルトでは以下になります。

発行者: https://identity.oraclecloud.com/

この値は、JWTのアクセス・トークンのiss属性の値になります。また、ORDS_SECURITY.CREATE_JWT_PROFILEを呼び出す際に、引数p_issuerとして指定する値になります。

デフォルト値をそのまま使用するため、取消をクリックしてドロワーを閉じます。


DefaultドメインにAPEXアプリケーションを作成します。

統合アプリケーションタブを開き、アプリケーションの追加をクリックします。


機密アプリケーションを選択し、ワークフローの起動をクリックします。


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

送信をクリックします。


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


OAuth構成タブを開き、OAuth構成の編集をクリックします。


リソース・サーバー構成を実施します。

このアプリケーションをリソース・サーバーとして今すぐ構成しますを選択します。

リソース・サーバー構成は、アクセス・トークンのscopeクレイムに、ORDSを保護している権限を追加するために必要です。ORDSの保護にJWTプロファイルを使用しない場合、この設定は不要です。

プライマリ・オーディエンスとしてapi://ords/ordsの部分はGUIDとするのが望ましい。また、OktaやMicrosoft Entra IDと異なり末尾に/が必要)を設定します。この値はアクセス・トークンのaud属性になります(より正確にはaud属性が配列になるため、その要素の1つになります)。また、ORDS_SECURITY.CREATE_JWT_PROFILEの引数p_audienceの値になります。後の設定で使うので、覚えておきます。

スコープの追加オンに変更し、スコープの追加をクリックします。


スコープには、ORDSのAPIを保護している権限と同じ名前を設定します。今回はORDSの権限としてmyordsappを作成しているため、myordsappとします。

ユーザー許諾が必要オンにします。これをオンにすると、アプリケーションへの初回サインイン時に、このスコープの使用を許可するかどうかをユーザーに確認します。

追加をクリックします。


スコープとしてmyordsappが追加されます。


リソース・サーバー構成は以上で完了です。

クライアント構成を実施します。

クライアント構成このアプリケーションをクライアントとして今すぐ構成しますを選択します。

認可許可される権限付与タイプから、最低限、認可コードチェックを入れます。OAuth2のAuthorization Code Grantsのことです。


リダイレクトURLとして、APEXをホストしているサーバーのURLにapex_authentication.callbackを付加したURLを設定します。

リダイレクトURLは以下のようになります。

https://[ホスト名]/ords/apex_authentication.callback

ログアウト後のリダイレクトURLはオプションですが、以下のように、APEXアプリケーションに作成済みのログアウト・ページを設定します。

https://[ホスト名]/ords/f?p=ORDS-JWT-TEST:LOGOUT:0::NO:::


クライアント・タイプ機密トークン発行ポリシー特定を選択します。リソースの追加オンに切り替えます。

リソース以下にスコープを追加する領域が表示されますが、リソース・サーバーに設定したスコープmyordsappがまだ保存されていません。そのため、追加するスコープが見つかりません。

ここで一旦送信をクリックします。


再度、OAuth構成の編集を開き、リソースの追加オンにします。

リソースに表示されるスコープの追加をクリックします。


ORDS JWT Testを開きapi://ords/myordsappをチェックします。この値が、APEXアプリケーションの認証スキーム有効範囲(scope)に含める値になります。

追加をクリックします。


以上でクライアント構成について編集が完了しました。

OAuth構成の編集は完了したので、送信します。


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

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


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


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


以上で、Oracle IAMへの機密アプリケーションの追加は完了しました。


OAuth構成タブを開き、一般情報クライアントIDクライアント・シークレットを取得します。これらの値は、APEXのWeb資格証明クライアントIDまたはユーザ名およびクライアント・シークレットまたはパスワードとして設定します。


Oracle APEXおよびORDSへの設定に必要な情報もすべて集まりました。

APEXでの作業に移ります。

ワークスペース・ユーティリティWeb資格証明を開きます。


APEXアプリケーションords-jwt-test.zipをインポートすると、Web資格証明としてOracle IAM JWT Testが作成されます。


Oracle IAMで作成したアプリケーションORDS JWT TestクライアントIDおよびシークレットを設定し、変更を適用します。


APEXアプリケーションORDS JWT Test共有コンポーネント認証スキームを開きます。


認証スキームOracle IAMを開きます。


Oracle IAMのDefaultドメインのドメインURL/.well-known/openid-configurationを加えたURLを、設定検出URLに設定します。また、有効範囲api://ords/myordsappを追加します。

変更を適用します。


認証スキームOracle IAMを再度開き、カレント・スキームにします


以上で、APEXアプリケーションがOracle IAMで認証されるようになりました。

APEXアプリケーションORDS JWT Testを実行します。


Defaultドメインへのサインイン画面が表示されます。(アプリケーションに自分のアカウントをユーザーとして割り当てているため)Oracle Cloudのコンソールへのサインインに使用しているユーザー名パスワードを入力します。

サインインをクリックします。


(MFAの設定によりますが)Oracle Mobile Authenticatorによる許可を求められます。


Oracle Mobile Authenticatorでアクセスを許可すると、要求したスコープへのアクセスの許可を求められます。この中にapi://ords/myordsappが含まれています。

許可をクリックします。


APEXアプリケーションORDS JWT Testのホーム・ページが開きます。ORDS REST APIの呼び出しは失敗しています。


JWTプロファイルを作成するにあたって、ORDS_SECURITY.CREATE_JWT_PROFILEの引数p_issuerhttps://identity.oraclecloud.com/p_audienceapi://ords/として設定済みです。引数p_jwk_urlの値であるJSON Web Tokenを取得するURLもすでに確認しています。

SQLワークショップSQLコマンドより、ORDS_SECURITY.CREATE_JWT_PROFILEを実行します。
begin
    ords_security.delete_jwt_profile;
    ords_security.create_jwt_profile(
        p_issuer => 'https://identity.oraclecloud.com/'
        ,p_audience => 'api://ords/'
        ,p_jwk_url => 'JSON Web Tokenを取得するURL'
    );
end;
/

APEXアプリケーションのホーム・ページに再度アクセスします。

今度はJWTプロファイルが設定されたため、正常にREST APIのレスポンスが表示されます。


以上でOracle IAMのOIDC認証にて、APEXアプリとそれから呼び出すORDSのREST APIを認証できました。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

追記


Oracle Help Center LearnのチュートリアルIntegrate Oracle APEX with Oracle Cloud Infrastructure Identity and Access Management Identity Domainsでは、認証後プロシージャとして以下のようなコードを記述し、APEXの動的グループを作成しています。本記事では動的グループについては扱っていません。
procedure load_dynamic_groups as
  l_group_names apex_t_varchar2;
begin
  --
  -- add all group names to l_group_names
  --
  for i in 1 .. apex_json.get_count('groups') loop
      apex_string.push (
        p_table => l_group_names,
        p_value => apex_json.get_varchar2 (
                       p_path => 'groups[%d].name',
                       p0     => i ));
  end loop;
  --
  -- save group names in session
  --
  apex_authorization.enable_dynamic_groups (
      p_group_names => l_group_names );
end;