前回は、Deep Data Securityの機能概要とローカル・エンドユーザーの実行例を紹介しました。今回は、Deep Data Securityの主要な目的であるトークン・ベース認証の外部エンド・ユーザーに対するアクセス制御の設定や動作を紹介します。
まず、Oracle Databaseのトークン・ベース認証についてですが、アプリケーションの用途によってOracle Databaseにアクセスする方式がいくつかあります。最も分かりやすいのは、下記のダイレクト・アクセスの方式です。
これは、自身のPCからSQLclやSQL DeveloperなどのSQLツール、VS CodeやClaude DesktopでOracle SQLcl MCP Serverを使ってデータベースにアクセスするなど、データベース接続に必要なアクセストークンを取得して渡すまでのフローは自身のPC内で完結するものです。
直接データベースを自由にアクセスできる管理者や開発者などの小規模なユーザー向けのアプリケーションが用途として該当します。現行のパスワード認証からEntraIDやOCI IAMのユーザーを各個人に払い出して、トークン認証に切り替えるだけなので、既存の使い方に対する影響は比較的軽微なものになるのではないかと思います。
今回はこのダイレクト・アクセス方式をドキュメントの設定例にエンドユーザー・コンテキストの要素を加えて、少し拡張した内容を紹介します。エンドユーザーコンテキストとは、ポリシーの条件等で使うために任意の値をセッション変数のように格納しておく方法です。
<前提> Entra IDとのトークン・ベース認証
今回はIdPを使用するので、こちらの手順を参考にOracle Database 23.26.2~とEntraIDとのトークン・ベースの認証が完了済みであること
Entra ID側の設定
新しいユーザーを作成。ユーザー名はそれぞれemmaとmarvinとする。

データ・ロールとマッピングさせるアプリ・ロール(EMPLOYEE, MANAGER)を作成する。アプリロール -> アプリロールの作成

次に作成したアプリロールが利用できるようにアクセス権を付与する
APIのアクセス許可 -> アクセス許可の追加 -> 自分のAPIをクリックし、自身のアプリケーションを選択する

アプリケーションの許可 -> Employeeをチェックして、アクセス許可を追加

既定のディレクトリに~をクリックし、以下のようにEMPLOYEEとMANAGERに付与されればOK

最後に作成したアプリロールをユーザーまたはグループに割り当てる
エンタープライズ・アプリ -> ユーザーとグループ -> Add user/group

同じ手順でmarvinには、EMPLOYEEとMANAGERの両方のロールを割り当てる。以下のよう作成できていればOK
Oracle Database側の設定
テスト・データの準備
-- HRユーザーの作成 ※NO AUTHENTICATIONオプションでHRはログインはできない
CREATE USER hr NO AUTHENTICATION
DEFAULT TABLESPACE users
QUOTA UNLIMITED ON users;
-- employees表の作成
CREATE TABLE hr.employees(
employee_id NUMBER PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50),
email varchar2(100),
job_code VARCHAR2(10),
department_id NUMBER,
ssn VARCHAR2(20),
salary NUMBER(10,2),
manager_id NUMBER
);
--データの投入 ※@<your-entraID-domain>の部分を自身のEntra IDのドメインに置き換える
--例) victoria@<your-entraID-domain> --> victoria@xxxxxxx.ONMICROSOFT.COM
INSERT INTO hr.employees VALUES (100, 'Marvin', 'Smith', 'marvin@xxxx.onmicrosoft.com', 'mgr', 1234, '543-65-7890', 12000, 1);
INSERT INTO hr.employees VALUES (200, 'Emma', 'Baker', 'emma@xxxx.onmicrosoft.com', 'ic', 1234, '304-12-3465', 2000, 100);
INSERT INTO hr.employees VALUES (300, 'Luis', 'Pitt', 'luis@xxxx.onmicrosoft.com', 'ic', 1234, '432-45-6076', 1250, 100);
INSERT INTO hr.employees VALUES (400, 'Daniel', 'Radcliff', 'daniel@xxxx.onmicrosoft.com', 'ic', 1234, '592-12-1234', 800, 100);
commit;
--表のデータを確認
select * from hr.employees
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL JOB_CODE DEPARTMENT_ID SSN SALARY MANAGER_ID
----------- ---------- --------- ------------------------------ -------- ---------------- ------------ ------ ----------
100 Marvin Smith marvin@xxxx.onmicrosoft.com mgr 1234 543-65-7890 12000 1
200 Emma Baker emma@xxxx.onmicrosoft.com ic 1234 304-12-3465 2000 100
300 Luis Pitt luis@xxxx.onmicrosoft.com ic 1234 432-45-6076 1250 100
400 Daniel Radcliff daniel@xxxx.onmicrosoft.com ic 1234 592-12-1234 800 100
EntraIDのアプリロールとマッピングするデータ・ロール等の作成
--データロールを作成
CREATE DATA ROLE employee_role MAPPED TO 'AZURE_ROLE=EMPLOYEE';
CREATE DATA ROLE manager_role MAPPED TO 'AZURE_ROLE=MANAGER';
-- CREATE SESSIONを持つ通常のDBロールを作成
CREATE ROLE db_role;
GRANT CREATE SESSION TO db_role;
-- データロールに作成したDBロールを付与
GRANT db_role TO employee_role;
GRANT db_role TO manager_role;
データ権限の作成
①一般社員用データ権限 (自分の行だけ参照できる。ssn列は更新可能)
-- employees表のemail列とエンドユーザー・セキュリティコンテキストのusernameが一致する行
-- すべての列がSELECT, ssn列はUPDATEを許可。mployee_roleデータロールに付与
CREATE OR REPLACE DATA GRANT hr.employees_own_record
AS SELECT, UPDATE(ssn)
ON hr.employees
WHERE upper(email) = upper(ORA_END_USER_CONTEXT.username)
TO employee_role;
②MGR用データ権限 (自分の部下の行が参照できる。ただし、ssn列は除く)
エンドユーザー・コンテキストに自身のemployee_idを代入し、それを条件に使用している
※エンドユーザーは実オブジェクトを持てないので、HRスキーマに作成しそれを参照するようなことをやっている
--HRのEMP_CTX.IDのエンドユーザーコンテキストを作成
CREATE OR REPLACE END USER CONTEXT HR.EMP_CTX USING JSON SCHEMA '{
"type": "object",
"properties": {
"ID": {
"type": "integer",
"o:onFirstRead": "HR.ctx_pkg.init_user_context"
}
}
}';
--エンドユーザー・コンテキスト:EMP_CTX.IDに自分のemployee_idをUpdateするプロシージャ
CREATE OR REPLACE PACKAGE hr.ctx_pkg AS
PROCEDURE init_user_context;
END;
/
CREATE OR REPLACE PACKAGE BODY hr.ctx_pkg AS
PROCEDURE init_user_context IS
sql_stmt VARCHAR2(4000);
BEGIN
sql_stmt := '
UPDATE END_USER_CONTEXT t
SET t.CONTEXT.ID = (
SELECT e.employee_id
FROM hr.employees e
WHERE upper(e.email) = upper(ora_end_user_context.USERNAME)
)
WHERE owner = ''HR''
AND name = ''EMP_CTX'';
';
EXECUTE IMMEDIATE sql_stmt;
END;
END;
/
--HRのコンテキストの操作に必要な権限をデータロール:manager_roleに付与
GRANT UPDATE ANY END USER CONTEXT TO HR;
GRANT CREATE ANY END USER CONTEXT TO HR;
CREATE ROLE IF NOT EXISTS hr_context_admin;
GRANT EXECUTE ON hr.ctx_pkg TO hr_context_admin;
GRANT hr_context_admin TO manager_role ;
--ディクショナリビューからHRのコンテキストを参照できるデータ権限をmanager_roleに付与
CREATE OR REPLACE DATA GRANT hr.EMPLOYEE_CONTEXT_GRANT
AS SELECT ON SYS.END_USER_CONTEXT
WHERE OWNER = 'HR' AND NAME = 'EMP_CTX'
TO manager_role ;
-- employees表のmanager_idとエンドユーザー・コンテキスト:EMP_CTX.IDが一致する行
-- ssn列以外はSELECT可
CREATE OR REPLACE DATA GRANT hr.HRAPP_MANAGER_ACCESS
AS SELECT (ALL COLUMNS EXCEPT ssn)
ON hr.employees
WHERE manager_id = ORA_END_USER_CONTEXT.HR.EMP_CTX.ID
TO manager_role;
エンドユーザー(Emma)で実行。自分行のみがSELECTできる
--emmaでログイン (※SQLclでインタラクティブ接続)
sql /@サービス名
--Entra IDのログイン画面にリダイレクトされるので、emma@xxxx.onmicrosoft.comでログイン。
--ログインが成功すればプロンプトが戻り、データベースに接続する
Copyright (c) 1982, 2026, Oracle. All rights reserved.
接続先:
Oracle AI Database 26ai EE High Perf Release 23.26.2.0.0 - Production
Version 23.26.2.0.0
--エンドユーザー・セキュリティコンテキストの値を確認
SQL> SELECT ORA_END_USER_CONTEXT.username FROM dual;
USERNAME
--------------------------------------------
emma@xxxx.onmicrosoft.com
--hr.emloyees表を検索。employee_role -> hr.employees_own_recordのデータ権限が適用
SQL> SELECT * FROM hr.employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL MANAGER SSN SALARY PHONE
----------- ---------- --------- --------------------------- --------------------------- ------------ ------ --------
400 Emma Baker emma@xxxx.onmicrosoft.com marvin@xxxx.onmicrosoft.com 733-02-9821 8200 555-0400
--salary列は権限ないので更新できない
SQL> UPDATE hr.employees SET salary = 9000;
0行更新しました。
--ssn列は更新できる
SQL> UPDATE hr.employees SET ssn = '111-222-3333';
1行更新しました。
エンドユーザー(Marvin)で実行。自分の行 + MANAGER列が自分のemployee_idになっている部下の行も表示。ただし自分以外のSSN列はNULL
--marvinでログイン (※SQLclでインタラクティブ接続)
sql /@サービス名
--Entra IDのログイン画面にリダイレクトされるので、marvin@xxxx.onmicrosoft.comでログイン。
--ログインが成功すればプロンプトが戻り、データベースに接続する
--エンドユーザー・セキュリティコンテキストの値を確認
SQL> SELECT ORA_END_USER_CONTEXT.username FROM dual;
USERNAME
----------------------------------------------
marvin@xxxx.onmicrosoft.com
--エンドユーザー・コンテキストの値を確認。自身のEMPLOYEE_ID:100が入っている
SQL> SELECT ora_end_user_context.HR.EMP_CTX.ID FROM DUAL;
EMP_CTX
__________
100
--hr.emloyees表を検索。employee_role -> hr.employees_own_recordと
-- manager_role -> hr.manager_direct_reportsのデータ権限が適用
SQL> SELECT * FROM hr.employees;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL JOB_CODE DEPARTMENT_ID SSN SALARY MANAGER_ID
----------- ---------- --------- ---------------------------- -------- ------------- ------------ ------ ----------
100 Marvin Smith marvin@xxxx.onmicrosoft.com mgr 1234 543-65-7890 12000 1
200 Emma Baker emma@xxxx.onmicrosoft.com ic 1234 2000 100
300 Luis Pitt luis@xxxx.onmicrosoft.com ic 1234 1250 100
400 Daniel Radcliff daniel@xxxx.onmicrosoft.com ic 1234 800 100
今回は、EntraIDのユーザーを直接アプリロールに割り当てました。より実務的には、グループをアプリロールに割り当てることで、ユーザーがグループへ参加した際に自動的にデータロール(データ権限)が付与されるという仕組みになります。利用しているEntraIDのグループがあれば、それに対応したアクセス・レベルを決め、データ権限の条件を考え、データロールに付与していくというのが基本設計になります。
また、今回のようなダイレクト・アクセスではなく、ERPのような業務アプリケーションやAnalytics、Enterprise AIシステムのような中間アプリケーションがある場合、アプリケーションはデータベースに単一の代表ユーザーでコネクション・プーリングを使い、データベースへの接続コストを効率化していることが多いかと思います。
コネクション・プーリングを毎回ユーザーごとに接続をするようにコードを変更することは、パフォーマンスの観点からやりたくないので、代わりにエンドユーザー・セキュリティ・コンテキストを既存のデータベース・セッションにアタッチするという方法があります。
エンドユーザー・セキュリティ・コンテキストとは、エンドユーザーのアイデンティや属性情報を格納しており、主にアクセストークンから生成されます。ダイレクト・ログインの場合は、データベース接続時に自動的に作成されているのですが、このエンドユーザー・セキュリティ・コンテキストをアプリケーション・コード内で明示的に生成することができます。
つまり、アプリケーションがデータベースにコネクション済みだとすると、プールから借りてきたコネクションにエンドユーザー・セキュリティ・コンテキストをアタッチして、IdPのエンド・ユーザーとしてSQLを実行させることができます。
そして、コネクションを返す際にデタッチする。既存のDBコネクションにアタッチ/デタッチしながらエンドユーザーを切り替えることで、コネクション・プーリングを維持しながらDeep Data Securityのエンドユーザーへのアクセス制御を実現します。
例えば、Javaの場合、oracle.jdbc.EndUserSecurityContextクラスをアプリケーションに実装します。Pythonや.NET、各フレームワークにも実装方法が用意されています。
中間アプリケーションの場合の構成例としては、OBO(On-Behalf-Of)フローによるエンドユーザー代理のアクセスとアプリケーションのIdentityを用いたアクセスの2種類の方式があるのですが、次回はこれらの違いやアプリケーションへの実装方法について紹介したいと思います。





