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

2023年6月6日火曜日

Azure ADのOIDC認証で取得したリフレッシュ・トークンを使ってアクセス・トークンを更新する

 KeycloakのOpen ID Connect認証で取得したリフレッシュ・トークンを使って、アクセス・トークンを更新する実装を見かけたので、Azure ADで同様の実装を試してみました。

以下から始まる一連の記事で行った実装への追加になります。

Microsoft OneDriveを操作するAPEXアプリの作成(1) - Azure ADへのアプリ登録

リフレッシュ・トークンは、Azure ADを使ったOpen ID Connect認証の応答であるJSONデータに含まれています。Oracle APEXの認証スキームの認証後のプロシージャに、リフレッシュ・トークンの取得と保存を行うコードを記述します。

取得したリフレッシュ・トークンを保存するために、アプリケーション・アイテムとしてG_REFRESH_TOKENを作成します。

共有コンポーネントアプリケーション・アイテムを開きます。


作成をクリックし、アプリケーション・アイテムG_REFRESH_TOKENを作成します。有効範囲アプリケーションセキュリティセッション・ステート保護はデフォルトの制限付き - ブラウザから設定不可のまま変更しません。トークンにエスケープされるような特殊文字は含まれないと考えているので、特殊文字をエスケープオンにしています。リフレッシュ・トークンを画面に表示することはないため、オフにしても問題ないでしょう。

アプリケーション・アイテムの作成をクリックします。


アプリケーション・アイテムが作成されます。


Azure ADを使っている認証スキームを開き、ソースPL/SQLコードに以下を記述します。Azure ADの応答からrefresh_tokenを取り出し、アプリケーション・アイテムG_REFRESH_TOKENに保存しています。


ソースに記述したプロシージャpost_authを、ログイン・プロセス認証後のプロシージャ名に設定します。

変更の適用をクリックして、保存します。


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

すでにOpen ID Connectによる認証に使用しているWeb資格証明が登録済みです。これは認証タイプOAuth2クライアント資格証明フローです。

同じクライアントIDクライアント・シークレットを使った基本認証Web資格証明を作成します。リフレッシュ・トークンを使ったアクセス・トークンの取得に、このWeb資格証明を使います。


Azure ADの画面より、登録済みのアプリケーションのアプリケーション(クライアントID)を確認し、コピーします。


クライアントの資格情報を開き、クライアント・シークレットを取得します。作成直後を除きコピーできないことから、再作成が必要な場合もあります。

この値もコピーしておきます。


リフレッシュ・トークンを発行するには、APIのアクセス許可(いわゆるスコープ - scope)にoffline_accessが含まれている必要があります。


クライアント・シークレットを再作成した場合は、認証タイプOAuth2クライアント資格証明フローWeb資格証明クライアント・シークレットまたはパスワードを更新します。


認証タイプ基本認証としたWeb資格証明を作成します。

名前はMS Azure Cred Basic静的IDMS_AZURE_AD_BASICとしています。認証タイプ基本認証を選択し、クライアントIDまたはユーザー名クライアント・シークレットまたはパスワードは、OAuth2クライアント資格証明フローと同じ情報を設定します。


アクセス・トークンのリフレッシュを行うための準備は以上になります。

実際にアクセス・トークンをリフレッシュする実装を行います。

ホーム・ページにリフレッシュを行うボタンRefresh Tokenを作成します。


ページ・デザイナホーム・ページを開き、ボタンを作成します。識別ボタン名REFRESH_TOKENラベルRefresh Token動作アクションはデフォルトのページの送信を選択します。


プロセス・ビューを開き、ボタンREFRESH_TOKENをクリックしたときに実行するプロセスを作成します。

識別名前Refresh Tokenタイプとしてコードを実行を選択します。ソースPL/SQLコードとして以下を記述します。


サーバー側の条件ボタン押下時REFRESH_TOKENを指定します。


以上で、アクセス・トークンを更新するボタンができました。

動作を確認してみます。

アプリケーションを実行し、Azure ADを使ってサインインをします。サインインに成功すると、ホーム・ページが開きます。


以下のMS Graph APIを呼び出し、ドライブの一覧を表示します。

https://graph.microsoft.com/v1.0/me/drives


認証スキームで使用しているWeb資格証明タイプOAuth2クライアント資格証明フロー)を開きます。ストアド・トークンアクセス・トークン(セッション)、つまりアクセス・トークンが保存されていることを確認します。

トークンのクリアをクリックします。


ページがWeb資格証明の一覧に戻るので、再度、対象のWeb資格証明を開きます。

アクセス・トークン(セッション)0になっています。


ボタンSubmitをクリックすると無効なURLというエラーが発生します。アクセス・トークンが無効(正確にいうと無くなっている)になっているので、ボタンRefresh Tokenをクリックし、アクセス・トークンを再取得します。


Web資格証明のページを再ロードすると、アクセス・トークン(セッション)1になっており、新たにアクセス・トークンが保存されていることが確認できます。


再度MS Graph APIを呼び出すと、今度はAPIが正常に応答し、アクセス・トークンが有効であることが確認できます。

APEXアプリケーションの最大セッションの長さ(秒)はデフォルトで通常3600秒なので、このままの設定であればリフレッシュ・トークンを使ってアクセス・トークンを更新する意味はそれほどない(アクセス・トークンの有効期間も3600秒であるため)かもしれません。

APEXアプリケーションの最大セッション長は、アプリケーション定義セキュリティセッション管理最大セッションの長さ(秒)を変更することで、長くすることができます。


以上になります。

以前に公開しているアプリケーションのエクストポートに、今回の実装を追加しました。
https://github.com/ujnak/apexapps/blob/master/exports/onedrive-operation.zip

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

2023年1月20日金曜日

Microsoft OneDriveを操作するAPEXアプリの作成(7) - ODataプラグイン

 せっかくMicrosoft Azure ADによるOIDC認証の構成を行ったので、RESTデータ・ソースを簡易HTTPからODataプラグインに置き換えてみました。

Oracle APEXのODataプラグインについては、以下のAPEX Office Hourで紹介されています。

APEX and OData? REST Data Sources at your service!
https://asktom.oracle.com/pls/apex/asktom.search?oh=19326


ODataプラグインのインストール


ODataプラグインは、GitHubの以下のリンクから取得できます。

odata_connector_sample_app.zipをダウンロードし、APEXのワークスペースに一般的なAPEXアプリケーションとしてインポートします。


ODataプラグインは以下のパッケージに実装されています。

PLG_ODATA_CONNECTOR
PLG_ODATA_FILTERS
PLG_ODATA_METADATA
PLG_ODATA_ORDER_BYS

これらのパッケージの作成は、サンプル・アプリケーションのインストール・スクリプトに含まれています。そのため、サンプル・アプリケーションをインポートする際にサポートするオブジェクトのインストールは必ずONにします。


ODataプラグインの実装であるweb_source_type_plugiin_odata-connector.sqlを、プラグインとしてインポートするだけでは上記のパッケージが作成されません。そのため、プラグインのインポートだけではODataプラグインは動作しません。

サンプル・アプリケーションのインポートが、ODataプラグインをインストールする最も簡単な方法です。


ODataプラグインの作成



共有コンポーネントプラグインを開きます。


作成済みのプラグインが一覧されます。作成をクリックします。


プラグインの作成として既存のプラグインのコピーを選択します。

へ進みます。


アプリケーションからコピーとしてSample ODATA-Connectorを選択します。

へ進みます。


コピー対象として、タイプRESTデータ・ソース名前OData REST Serviceというプラグインが表示されます。

コピーしますか?として、はいまたはコピーおよびサブスクライブのどちらかを選択します。

プラグインのコピーをクリックします。


ODataプラグインが作成されました。


OData REST ServiceプラグインによるRESTデータ・ソースが作成できるようになりました。


RESTデータ・ソースの作成



今までの記事で作成したRESTデータ・ソース、My Drives、My Root、My Folderと同じRESTデータ・ソースを、OData REST Serviceプラグインを使用して作成します。

作成済みのRESTデータ・ソースのエンドポイントURLをメモしておきます。OData REST Serviceプラグインでは、簡易HTTPでのエンドポイントURLを、エンドポイントURLResource Pathに分割して登録します。


はじめにMy Drivesと同じRESTデータ・ソースを作成します。

RESTデータ・ソース・タイプとしてOData REST Serivce[プラグイン]を選択します。名前OData My Drivesとします。URLエンドポイントとして、以下を指定します。

https://graph.microsoft.com/v1.0/me/

へ進みます。


リモート・サーバーおよびサービスURLパスは自動的に決まります。

変更せずにへ進みます。


OData REST Serviceプラグインとしての設定になります。

Resource Pathdrivesとします。エンドポイントURL + Resource Pathが実際にリクエストされるGraph APIのURLです。

へ進みます。


認証を設定します。

これ以降は、タイプが簡易HTTPで作成したRESTデータ・ソースMy Drivesと同じ作業を行います。サンプル・レスポンスdrives.jsonを使用してデータ・プロファイルを更新します。


OData REST SerivceプラグインによるRESTデータ・ソースでは、ODataとしてサポートされている機能を選択する必要があります。サポートされていない機能が有効になっていると、REST APIの発行時にエラーが発生します。

Microsoftのドキュメントより、サポートされている機能を確認します。

Microsoft Graphでのファイルの作業

ドライブを一覧表示するでは、以下のように$expand$select$skipToken$top$orderbyがサポートされているとのことです。


設定項目のオンライン・ヘルプに、対応するODataのクエリパラメーターの説明が記述されています。

このRESTデータ・ソースでは、Basic OptionsSource supports orderingSource supports querying of specific columnsにチェックを入れます。


Source supports client-driven paginationですが、ページネーションはOData REST Serivceプラグインではクエリパラメーターの$top$skipを使って実施します。Microsoftの以下のドキュメントによると、$skipは問題があるため$skipTokenを代わりに使うとのことです。

Use $skiptoken for server-driven paging
https://learn.microsoft.com/en-us/odata/webapi/skiptoken-for-server-side-paging

OData REST Serviceプラグインは$skipTokenを使用したページネーションをサポートしていないため、Graph APIが$skipではなく$skipTokenを実装している場合は、Source supports clilent-driven paginationにチェックを入れることはできません。

続いてMy Rootと同じRESTデータ・ソースOData My Rootを作成します。

Resource Pathdrive/root/childrenになります。その他は、My Rootの作成と同じ手順になります。


ドライブの項目子を一覧表示するオプションのクエリパラメーターは以下です。


先ほどと同じなので、Basic OptionsSource supports orderingSource supports querying of specific columnsにチェックを入れます。


最後にMy Folderと同じRESTデータ・ソースOData My Folderを作成します。

Resource Pathとしてdrive/items/:item_id/childrenを指定します。Resource Pathに含まれるパラメータはURLエンドポイントとは異なり、パラメータとして自動的に検出されません。そのため、RESTデータ・ソース作成後に手作業でパラメータitem_idを追加します。

これ以降の作業はRESTデータ・ソースMy Folderと同じです。


RESTデータ・ソースOData My Folderを作成し、Basic Optionsの設定を行った後に、パラメータの追加を行います。


パラメータの追加をクリックします。


パラメータタイプとしてURLパターン変数を選択します。名前item_idデフォルト値になります。フォルダのDriveItemのIDを入力しておきます。空でも問題ありません。

目的入力詳細必須ONにします。

以上で、パラメータの追加をクリックします。


パラメータが追加されました。変更の適用をクリックします。


以上で、RESTデータ・ソースOData My DrivesOData My RootOData My Folderの作成は完了です。




対話モード・レポートの更新



作成済みの対話モード・レポートのデータ・ソースを入れ替えます。

レポートMy Drivesについては、ソースRESTソースをMy DrivesからOData My Drivesに変更するだけです。


レポートMy Rootでは、ソースの変更前にローカル後処理SQL問合せコピーを取得しておきます。


ソースRESTソースOData My Rootに変更します。ローカル後処理が初期化されるため、先ほどコピーした値で設定を回復します。


レポートFolderRESTソースOData My Folderに変更します。ローカル後処理SQL問合せは元の設定をコピーし、ソース変更後に回復させます。


レポートFolderの場合、パラメータの設定もリセットされます。

パラメータitem_idを選択し、タイプアイテムアイテムP3_ITEM_IDに設定し直します。


以上で対話モード・レポートの更新は完了です。


ODataプラグインのデバッグ



以上の設定でアプリケーションを実行すると、レポートの表示でエラーが発生しました。


最初にデバッグ出力を有効にして、エラー・メッセージを確認します。


エラー・メッセージは以下です。\"@microsoft, という部分が悪いことはわかりますが、これだけだとデバッグは難しいです。

Parsing OData Select and Expand failed: Syntax error: character '\"' is not valid at position 128 in 'eTag,file,size,lastModifiedBy,createdDateTime,folder,webUrl,fileSystemInfo,cTag,shared,reactions,name,createdBy,parentReference,\"@microsoft,specialFolder,lastModifiedDateTime,id

APEXから発行されたREST APIへのリクエストは、ビューAPEX_WEBSERVICE_LOGから確認できます。

アプリケーション・ビルダーワークスペース・ユーティリティから、Oracle APEXビューを開きます。


ビューの一覧よりAPEX_WEBSERVICE_LOGを探して、開きます。


としてURLHTTP_METHODSTATUS_CODEREQUEST_DATEを含めて、結果をクリックします。


フィルタを設定するなどして行を絞り込み、エラーが発生したURLを特定します。

特定したURLをコピーしておきます。


Graph APIを直接発行する画面より、コピーしたURLを呼び出します。同じエラーが発生します。


"@microsoft,の部分の除き、APIを発行すると成功します。


以上より、ODataのクエリパラメータ$selectに渡されている引数に問題があることがわかります。

RESTデータ・ソースのデータ・プロファイルより、@microsoftで始まるセレクタを確認します。

DOWNLOADURLが見つかりました。


DOWNLOADURLのセレクタは"@microsoft.graph.downloadUrl"ですが、このような形式のセレクタをOData REST Sourceプラグインは正しく扱えないようです。


列DOWNLOADURLはアプリケーションで使用しているため、削除することはできません。

設定Source supports querying of specific columnsのチェックを外すことで対応します。


RESTデータ・ソースOData My RootOData My Folderともに、この設定を外すことにより、ODataプラグインによるRESTデータ・ソースに変更したアプリケーションが動作するようになります。

$skipTokenやセレクタなど、OData REST ServiceプラグインのMicrosoft Graph APIとの互換性については残念な部分もありますが(オープンソースなので自分で修正することもできます)、OData自体は将来性があると思います。

変更後のアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/onedrive-operation-odata.zip

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

追記

パッケージplg_odata_connector.pkbに以下の記述があり、この部分(regexp_replace)がOneDriveのGraph APIと互換性がないようです。セレクタにはピリオドが含まれないという前提になっています。Graph APIは属性valueにJSONオブジェクトの配列が返しますが、一行にあたるJSONオブジェクトはスカラー値のみを含みJSONオブジェクトは含まない、と想定されているようです。
        --
        -- Cleanup the requested attribute before selection
        --
        l_requested_column_list := regexp_replace( l_requested_column_list, '\.[^\,]*' );

        select distinct
            regexp_replace( column_value, '\.[^\,]*' )
        bulk collect into
            l_arr_requested_attribute
        from
            apex_string.split( l_requested_column_list, ',' );

        l_requested_column_list := apex_string.join( l_arr_requested_attribute, ',' );

さて、どうしたものかとは思いますが、オープンソースだと自分で調べることはできます。