2024年2月8日木曜日

APEXセッションごとにGoogle Service Accountによるアクセス・トークンを取得する

先日、Google Analytics 4のAnalytics Data APIを呼び出すサンプル・アプリケーションを作成しています。

APIを呼び出すために、あらかじめGoogleのサービスアカウントで生成したアクセス・トークンを、Web資格証明に保存しておくことが前提でした。APIの呼び出しテストであればこれでも動きますが、実用性はありません。

APEXのセッション毎にアクセス・トークンを取得するためには、APEXアプリケーションからGoogleのサービスアカウントの秘密キーにアクセスする必要があります。OCI VaultにGoogleのサービスアカウントの秘密キーをインポートして、その上で電子署名の生成を試したことがありますが、うまくできませんでした。

次善の策として、Googleのサービスアカウントに関する情報をJSON形式で保存して、APEXアプリケーションからは、OCI Vaultからシークレットを取り出してアクセス・トークンを取得するようにしてみました。

ホーム・ページにアクセス・トークンを取得するボタンを追加しています。


ボタンをクリックしたときに実行されるコードです。APEX_CREDENTIAL.SET_PERSISTENT_CREDENTIALSの代わりにAPEX_CREDENTIAL.SET_SESSION_CREDENTIALSを呼び出しています。

declare
l_principal varchar2(400);
l_scope varchar2(400);
l_secret_data varchar2(4000);
l_jwt varchar2(32767);
l_token varchar2(32767);
begin
/*
* OCI Vaultにシークレットとして保存されているJSON形式の認証データを取り出す。
* 以下の形式で保存されていることが前提。
* {
* "principal": "サービスアカウントのメール",
* "scope": "スコープ",
* "secret_data": "PKCS#8形式の秘密キー"
* }
*/
utl_cred_google.get_secret_from_vault(
p_secret_id => :G_SECRET_ID
,p_region => :G_REGION
,p_credential_static_id => :G_OCI_CREDENTIAL
,p_principal => l_principal
,p_scope => l_scope
,p_secret_data => l_secret_data
);
/*
* JWTを生成する。
*/
l_jwt := utl_cred_google.generate_jwt(
p_secret => l_secret_data
,p_scope => l_scope
,p_iss => l_principal
);
/*
* 取得したJWTを一旦Web資格証明に保存する。
* Web資格証明として保存していると、APEX_WEB_SERVICE.MAKE_REST_REQUEST
* 呼び出し時にAPEX_WEBSERVICE_LOGに記載されない。
*
* 保存先となるWeb資格証明はあらかじめ作成しておく。
*/
apex_credential.set_session_credentials(
p_credential_static_id => :G_GA4_CREDENTIAL_JWT
,p_username => 'assertion'
,p_password => l_jwt
);
/*
* アクセス・トークンを取得する。
*/
l_token := utl_cred_google.get_token(
p_jwt_credential_static_id => :G_GA4_CREDENTIAL_JWT
);
/*
* 取得したアクセス・トークンを保存する。
*/
apex_credential.set_session_credentials(
p_credential_static_id => :G_GA4_CREDENTIAL_TOKEN
,p_username => 'Authorization'
,p_password => l_token
);
end;


アプリケーション定義置換文字列に、Analytics Data APIの認証に必要な情報を設定します。

G_SECRET_IDにOCI Vaultに保存されているシークレットのOCIDを設定します。

G_REGIONに使用しているOCI Vaultのリージョンを設定します。

G_OCI_CREDENTIALにOCI Vaultからシークレットのコンテンツを取り出す際に指定する、OCIのAPIのアクセスに使用するWeb資格証明を設定します。

G_GA4_CREDENTIAL_JWTに、サービス・アカウントの秘密キーを使って生成したJWTを保存するWeb資格証明を設定します。このWeb資格証明は、タイプURL問合せ文字列で、あらかじめ作成済みである必要があります。

G_GA4_CREDENTIAL_TOKENに、生成したJWTで取得したアクセス・トークンを保存するWeb資格証明を設定します。このWeb資格証明は、タイプHTTPヘッダーで、あらかじめ作成済みである必要があります。


APEXアプリケーションの認証後アプリケーション・プロセスとしてアクセス・トークンの取得を実行したり、APEX_WEB_SERVICE.MAKE_REST_REQUESTの呼び出しで401 Unauthorizedのレスポンスを受けた時にアクセス・トークンの取得をやり直して、APIの呼び出しを再実行するようにすると、APEXアプリケーションの利用者はAPI認証について意識する必要がなくなるでしょう。

今回の記事は以上です。

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