Oracle ERP Cloud Integration Security Roles: Minimum Privilege Design
TL;DR
- Bottom line: Create custom integration roles by copying predefined duty roles and stripping unnecessary privileges rather than assigning broad seeded job roles like Financial Application Administrator to integration users.
- Key limit: Integration users require BOTH function security privileges (what actions) AND data security policies (which data) -- function security alone does not grant data access.
- Watch out for: Seeded roles include far more privileges than integrations need -- the Integration Specialist role includes UI navigation and approval privileges that create SoD violations when assigned to service accounts.
- Best for: Any Oracle Fusion Cloud ERP integration using REST APIs, SOAP web services, FBDI file imports, or BI Publisher report extracts.
- Authentication: OAuth 2.0 (JWT assertion for server-to-server), SAML for SOAP, or basic auth over HTTPS -- all require the integration user to have the correct role assignments in Security Console.
System Profile
Oracle Fusion Cloud ERP uses a layered RBAC (Role-Based Access Control) model where security is enforced through job roles, duty roles, and privileges organized in a strict hierarchy. Integration security applies across all modules -- Financials, Procurement, Supply Chain Management, HCM, and Project Management. This card covers Release 24A through 25D. On-premise Oracle E-Business Suite uses a fundamentally different security model and is not covered here.
| Property | Value |
|---|---|
| Vendor | Oracle |
| System | Oracle Fusion Cloud ERP (Release 25A-25D) |
| API Surface | REST, SOAP, FBDI, BIP |
| Current API Version | Release 25D (quarterly updates) |
| Editions Covered | Enterprise (cloud-only) |
| Deployment | Cloud |
| API Docs | Oracle ERP Cloud Security Guide |
| Status | GA |
API Surfaces & Capabilities
Oracle ERP Cloud exposes multiple integration surfaces, each requiring different security role configurations. The security model applies consistently across all surfaces, but the specific duty roles and privileges differ.
| API Surface | Protocol | Best For | Security Requirement | Auth Method | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| REST API | HTTPS/JSON | Individual record CRUD, lookups | API-specific duty roles + data security | OAuth 2.0 / JWT | Yes | No |
| SOAP Web Services | HTTPS/XML | Complex operations, legacy integrations | Service-specific privileges + data roles | SAML / WS-Security | Yes | No |
| FBDI (File-Based Data Import) | UCM + ESS | Bulk data loads (AP invoices, journals) | Module duty roles + ESS privileges | Basic Auth / OAuth | No | Yes |
| BI Publisher (BIP) | HTTPS/XML | Report extracts, data exports | BI role + report-specific access | Basic Auth / OAuth | No | Yes |
| Business Events | Oracle Integration Cloud | Event-driven callbacks | Event subscription privileges | Token-based | Yes | N/A |
| ADF/Web Services | HTTPS/XML-SOAP | UI-level service operations | Full module job roles | SAML | Yes | No |
Rate Limits & Quotas
Per-Request Limits
| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| REST API payload size | 5 MB | REST API requests | Split larger payloads into multiple requests |
| FBDI file size | 250 MB per file | File uploads to UCM | Use multiple files for larger data sets |
| SOAP message size | 25 MB | SOAP web service calls | Configurable via admin but default is 25 MB |
| REST query results | 500 records default | REST GET operations | Use offset/limit for pagination |
| BIP report output | 300 MB | BI Publisher report generation | Large reports must be scheduled |
Rolling / Daily Limits
| Limit Type | Value | Window | Notes |
|---|---|---|---|
| REST API calls | No published hard limit | N/A | Fair-use throttling applies; Oracle monitors abnormal usage |
| ESS job submissions | 50 concurrent jobs | Per pod | FBDI imports count toward ESS job limits |
| UCM file uploads | 1,000 per hour | Per user | Applies to FBDI data file staging |
| Business Event subscriptions | 50 per integration | Per OIC instance | Each subscription requires its own role configuration |
Authentication
| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 (JWT Assertion) | Server-to-server REST integrations | Configurable (default 1h) | New JWT per request | Recommended for production integrations |
| SAML Assertion | SOAP web service calls | Session-based | No | Requires Identity Provider federation |
| Basic Auth (Username/Password) | Development, testing, FBDI uploads | Session timeout | No | Must be over HTTPS; not recommended for production REST |
| OAuth 2.0 (Authorization Code) | User-context REST operations | 1h access token | Yes (refresh token) | For integrations acting on behalf of a specific user |
Authentication Gotchas
- JWT assertion flow requires registering a confidential application in Oracle Identity Cloud Service (IDCS) or OCI IAM -- the client ID and secret must be managed as secrets, not embedded in integration code. [src1]
- The integration user must be a separate, dedicated user -- never share a human user's credentials for integrations because it breaks audit trails and complicates role certification. [src7]
- Session timeout settings configured by the Oracle Cloud administrator affect all authentication flows -- if sessions are shortened for security, integration tokens may expire mid-batch. [src1]
Constraints
- Integration users must have both function security privileges AND data security policies -- function security alone allows the API call but returns empty results without data security.
- Predefined (seeded) roles cannot be modified -- you must copy them first in Security Console before customizing.
- Duty roles cannot be assigned directly to users -- they must be nested inside job roles or abstract roles.
- Role changes require user re-provisioning -- the integration user must sign out and back in for new role assignments to take effect.
- FBDI imports require ESS (Enterprise Scheduler Service) scheduling privileges in addition to the module-specific import duty roles.
- REST API endpoints each have their own duty role -- a role granting access to GL journals does not automatically grant access to AP invoices.
- Cross-module integration users accumulate privileges that may trigger SoD (Segregation of Duties) violations.
Integration Pattern Decision Tree
START -- Design security roles for Oracle ERP Cloud integration
|-- What integration surface?
| |-- REST API
| | |-- Identify each REST endpoint your integration calls
| | |-- Map endpoints to API-specific duty roles (see Quick Reference)
| | |-- Create custom job role -> nest required API duty roles
| | |-- Assign data security policies for each business unit/ledger
| | +-- Authentication: OAuth 2.0 JWT assertion (recommended)
| |-- SOAP Web Services
| | |-- Identify WSDL services required
| | |-- Map to service operation privileges
| | |-- Create custom job role -> nest service duty roles
| | +-- Authentication: SAML assertion
| |-- FBDI (File-Based Data Import)
| | |-- Identify import templates needed
| | |-- Assign module-specific import duty roles
| | |-- Add ESS scheduling privilege
| | |-- Add UCM content access privileges
| | +-- Authentication: Basic auth (upload) + ESS job scheduling
| +-- BI Publisher (BIP) Extracts
| |-- Identify reports needed
| |-- Assign BI Consumer or BI Author role
| +-- Authentication: Basic auth or OAuth
|-- How many modules?
| |-- Single module -> one custom integration job role
| |-- Multiple modules -> evaluate SoD risk first
| | |-- Option A: one integration user per module (safest)
| | +-- Option B: one integration user, multi-module role (faster, riskier)
+-- What data scope?
|-- Single business unit -> restrict data role to that BU
|-- Multiple business units -> create data role per BU
+-- All business units -> use "Grant on all values" (audit carefully)
Quick Reference
Key Predefined Integration Roles by Module
| Module | Predefined Role | Role Code | What It Grants | Integration Surface |
|---|---|---|---|---|
| Financials (GL) | Financial Integration Specialist | ORA_GL_FINANCIAL_INTEGRATION_SPECIALIST | Journal import, GL inquiry, period operations | FBDI, REST, SOAP |
| Financials (AP) | Accounts Payable Integration Specialist | ORA_AP_ACCOUNTS_PAYABLE_INTEGRATION_SPECIALIST | Invoice import, payment processing | FBDI, REST |
| Financials (AR) | Receivables Integration Specialist | ORA_AR_RECEIVABLES_INTEGRATION_SPECIALIST | Receipt processing, customer import | FBDI, REST |
| Financials (FA) | Asset Integration Specialist | ORA_FA_ASSET_INTEGRATION_SPECIALIST | Asset mass additions, transfers | FBDI |
| Procurement | Procurement Integration Specialist | ORA_PO_PROCUREMENT_INTEGRATION_SPECIALIST | PO import, supplier management | FBDI, REST |
| SCM (Inventory) | Inventory Integration Specialist | ORA_INV_INVENTORY_INTEGRATION_SPECIALIST | Item import, on-hand transactions | FBDI, REST |
| SCM (Order Mgmt) | Order Management Integration Specialist | ORA_OM_ORDER_MANAGEMENT_INTEGRATION_SPECIALIST | Sales order import, fulfillment | FBDI, REST |
| HCM | Integration Specialist | ORA_HCM_INTEGRATION_SPECIALIST | Worker data import, absence management | FBDI, REST, HDL |
| Projects | Project Integration Specialist | ORA_PA_PROJECT_INTEGRATION_SPECIALIST | Project/task import, cost transactions | FBDI, REST |
Duty Roles Commonly Needed for REST API Access
| API Endpoint Category | Required Duty Role | Privilege Example | Notes |
|---|---|---|---|
| GL Journals | General Accounting Duty | Create Journal, Import Journal | Must pair with ledger data security |
| AP Invoices | Accounts Payable Invoice Duty | Create AP Invoice, View AP Invoice | Must pair with BU data security |
| AR Receipts | Receivables Transaction Duty | Create AR Receipt, Apply AR Receipt | Must pair with BU data security |
| Suppliers | Supplier Maintenance Duty | Create Supplier, Update Supplier | Must pair with procurement BU data security |
| Purchase Orders | Purchasing Transaction Duty | Create Purchase Order, View Purchase Order | Must pair with BU and requisitioning BU |
| Items/Inventory | Item Management Duty | Create Item, Update Item | Must pair with inventory organization data security |
| Employees/Workers | Worker Management Duty | View Worker, Create Person | HCM-specific data roles required |
Step-by-Step Integration Guide
1. Create a Dedicated Integration User
Create a separate user account exclusively for the integration. Never reuse a human user account. [src7]
Navigation: Setup and Maintenance > Manage Users
1. Click "Add User" or use SCIM REST API
2. Set User Name: INT_<SYSTEM>_<MODULE> (e.g., INT_OIC_FINANCIALS)
3. Set a strong password (if using basic auth) or leave password-less for OAuth-only
4. Do NOT assign any seeded job roles at this stage
Verify: Navigate to Security Console > Users > search for the new user -> user should exist with zero roles assigned.
2. Design a Custom Integration Job Role
Create a minimal custom job role that nests only the required duty roles. [src2, src4]
Navigation: Tools > Security Console > Roles > Create Role
1. Role Name: Custom <Module> Integration Role
2. Role Code: CUSTOM_INT_GL (your naming convention)
3. Role Category: Common
4. Click "Duty Roles" tab > Add Duty Role
5. Search and add ONLY the duty roles your integration needs
6. Click "Function Security Policies" tab
7. Verify only necessary privileges are inherited
8. REMOVE any unnecessary privileges (UI navigation, approvals)
Verify: Security Console > Roles > search your custom role > "Privilege" tab -> verify no unnecessary privileges exist.
3. Configure Data Security Policies
Data security defines WHICH data the integration can access. Without this, the integration user calls APIs but gets empty results. [src1, src6]
Navigation: Security Console > Roles > [Your Custom Role] > Data Security Policies
1. Click "Create Data Security Policy"
2. Database Resource: select the business object (e.g., "Ledger", "Business Unit")
3. Dataset: select the condition
- "Select by instance set" -> specific ledger(s) or BU(s)
- "Grant on all values" -> all records (use sparingly)
4. Actions: select only needed actions (Read, Manage)
5. Repeat for each business object the integration touches
Verify: Sign in as the integration user -> call the REST API -> confirm response contains only expected records.
4. Assign the Custom Role to the Integration User
Assign only the custom role -- no seeded job roles. [src2]
Navigation: Security Console > Users > [Integration User] > Roles > Add Role
1. Search for your custom role (e.g., "Custom GL Integration Role")
2. Click "Add Role Membership"
3. Set Provisioning Status to "Provisioned"
4. Click Save
Verify: Security Console > Users > [Integration User] > "Roles and Role Memberships" tab -> confirm only your custom integration role appears.
5. Configure FBDI-Specific Privileges (If Using File Import)
FBDI requires additional privileges beyond module-level duty roles. [src3]
Add these duty roles to your custom integration job role:
1. "Manage File Import and Export" (for UCM file staging)
2. "Run <Module> Scheduled Processes" (for ESS job submission)
3. "Import <Object>" privilege specific to your import template
Add UCM content security for relevant content folders.
Verify: Sign in as the integration user -> navigate to Scheduled Processes -> confirm only relevant import jobs are visible.
6. Validate and Test the Configuration
Test all API endpoints the integration will use with the actual integration user credentials. [src7]
# Test REST API access with the integration user
curl -X GET \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/journals" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json"
# Expected: 200 OK with journal data for assigned ledgers only
# 403 = missing function security; 200 with empty items[] = missing data security
Verify: Response contains data ONLY for the assigned ledgers/business units.
Code Examples
Python: Audit Integration User Privileges via REST API
# Input: Oracle ERP Cloud instance URL, OAuth access token
# Output: List of all roles and privileges assigned to integration user
import requests
base_url = "https://<instance>.fa.ocs.oraclecloud.com"
token = "<oauth_access_token>"
username = "INT_OIC_FINANCIALS"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
resp = requests.get(
f"{base_url}/hcmRestApi/resources/latest/userAccounts",
params={"q": f"Username={username}", "expand": "roles"},
headers=headers
)
if resp.status_code == 200:
user_data = resp.json()
for item in user_data.get("items", []):
print(f"User: {item.get('Username')}")
for role in item.get("roles", []):
print(f" Role: {role.get('RoleName')} ({role.get('RoleCode')})")
else:
print(f"Error: {resp.status_code} - {resp.text}")
cURL: Test Integration User REST API Access Per Module
# Input: Instance URL, integration username, password
# Output: HTTP status codes per module endpoint
# Test GL access
curl -s -o /dev/null -w "%{http_code}" \
-u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/journals?limit=1"
# Test AP access
curl -s -o /dev/null -w "%{http_code}" \
-u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/invoices?limit=1"
# Verify data scope: count accessible ledgers
curl -s -u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/ledgers" \
| python -c "import sys,json; d=json.load(sys.stdin); print(f'Accessible ledgers: {d.get(\"count\",0)}')"
Data Mapping
Security Object Hierarchy
| Security Layer | Oracle Term | Purpose | Example | Assignable To Users? |
|---|---|---|---|---|
| Job Role | Job Role | Top-level role representing a job function | Financial Integration Specialist | Yes |
| Abstract Role | Abstract Role | Cross-functional role (Employee, Contingent Worker) | Employee | Yes |
| Duty Role | Duty Role | Logical group of related privileges | General Accounting Duty | No (nest in job role) |
| Function Privilege | Function Security Privilege | Atomic permission to perform an action | Create Journal Entry | No (nest in duty role) |
| Data Security Policy | Data Security Policy | Grant to access specific data rows | Access Ledger: Vision Operations | No (attach to duty/job role) |
| Data Role | Data Role | Job role + data security combined | US Financials Integration Data Role | Yes |
Data Type Gotchas
- Function security privileges are cumulative (additive) -- there is no "deny" privilege. To restrict access, do not include the privilege in the role. [src1]
- Data security policies use conditions referencing "set" columns (SetId, BusinessUnitId, LedgerId). If using reference data sets, the integration user needs access to both the transaction BU and the reference data set. [src6]
- Role inheritance is unlimited depth. When auditing privileges, trace the full inheritance chain using Security Console > "Privilege" tab > "Inherited Roles" view. [src5]
Error Handling & Failure Points
Common Error Codes
| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 403 Forbidden | Function security violation | Integration user lacks the API-specific duty role or privilege | Add the required duty role via Security Console |
| 200 with empty items[] | Data security violation (silent) | User has function access but no data security for the target data set | Add data security policy for the specific ledger/BU/org |
| 401 Unauthorized | Authentication failure | Invalid credentials, expired token, or user locked | Verify credentials; check if user is active; regenerate token |
| 500 Internal Server Error | Privilege conflict | Role configuration creates circular references or missing dependencies | Review role hierarchy in Security Console |
| JBO-26061 | Data security policy violation | Attempted operation on data outside granted scope | Expand data security policy to include missing BU or ledger |
| FND-0062 | Privilege not found | Referenced privilege code does not exist in current release | Check privilege code against current release documentation |
Failure Points in Production
- Silent data filtering: REST APIs return 200 OK with empty results when data security is missing. Fix:
Always validate record counts against a known baseline after role changes.[src1] - Role provisioning delay: After assigning a new role, the user must log out and back in before privileges take effect. Fix:
Run the "User and Roles Synchronization" ESS job to force re-provisioning.[src2] - Quarterly update privilege changes: Oracle updates can rename or deprecate duty roles and privileges. Fix:
After every quarterly update, run a privilege comparison report using Security Console "Compare Roles" feature.[src4] - FBDI "Insufficient Privileges" error: Integration user has module duty roles but is missing the ESS scheduling privilege. Fix:
Add "Run <Module> Scheduled Processes" duty role to the integration job role.[src3] - Cross-module SoD violations: Integration user touching both AP and GL may trigger SoD alerts. Fix:
Use separate integration users per module or document the exception with compensating controls.[src7]
Anti-Patterns
Wrong: Assigning Seeded Job Roles Directly to Integration Users
# WRONG -- assigning broad seeded roles
Security Console > Users > INT_OIC_ALL > Add Role
Role: "General Accountant" # 200+ privileges, includes approvals
Role: "Accounts Payable Manager" # includes payment approvals and UI nav
Role: "Procurement Manager" # includes sourcing and negotiation
Correct: Creating Minimal Custom Integration Roles
# CORRECT -- custom role with only needed duty roles
Security Console > Roles > Create Role
Role Name: "Custom Financials Integration Role"
Duty Roles:
- "General Accounting Duty" # journal operations only
- "Accounts Payable Invoice Duty" # invoice CRUD only, no approvals
- "Run Financials Scheduled Processes" # ESS for FBDI
Data Security:
- Ledger: "US Primary Ledger" only
- Business Unit: "US Business Unit" only
Wrong: Using "Grant on All Values" for Data Security
# WRONG -- granting access to ALL business units/ledgers
Data Security Policy:
Database Resource: Business Unit
Condition: "Grant on all values" # sees ALL BUs globally
Correct: Restricting Data Security to Specific Business Units
# CORRECT -- granting access only to required business units
Data Security Policy:
Database Resource: Business Unit
Condition: "Select by instance set"
Business Units: ["US Business Unit", "UK Business Unit"]
Wrong: Sharing a Human User Account for Integrations
# WRONG -- using a named user for integration
Integration Connection:
Username: "john.smith" # human user
# breaks audit trail, SoD conflict, breaks when John leaves
Correct: Using Dedicated Integration Service Accounts
# CORRECT -- dedicated service account
Integration Connection:
Username: "INT_OIC_GL" # dedicated, non-human user
Auth: OAuth 2.0 JWT assertion # no password to rotate
Roles: "Custom GL Integration Role" only
Common Pitfalls
- Copying too much from seeded roles: Copied roles inherit ALL duty roles from the seeded role. Fix:
Start with an empty custom role and ADD only the duty roles you need.[src4] - Forgetting data security for REST APIs: Function security controls which endpoints the user can call; data security controls which records are returned. Fix:
For every duty role added, identify the corresponding data security policy and add both.[src1] - Testing with admin credentials: Developers test with their own admin accounts, then integration fails in production with the minimal integration user. Fix:
Always test API calls using the actual integration user credentials before go-live.[src7] - Ignoring quarterly update impact: Quarterly updates can introduce new privileges or restructure duty role inheritance. Fix:
Re-validate integration user access after every quarterly update.[src4] - Over-provisioning to "make it work": Adding broader roles when an integration fails creates security liability and SoD violations. Fix:
Use Security Console "Analyze Roles" to identify the specific missing privilege.[src2] - Not managing multiple environments: Role definitions do not auto-migrate between environments. Fix:
Export role definitions using the "Security Setup Data" implementation project task.[src1]
Diagnostic Commands
# List all roles assigned to integration user
curl -s -u "admin_user:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/hcmRestApi/resources/latest/userAccounts?q=Username=INT_OIC_FINANCIALS&expand=roles" \
| python -m json.tool
# Test function security: attempt GL journal query
curl -s -w "\nHTTP Status: %{http_code}\n" \
-u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/journals?limit=1"
# Test data security: count accessible ledgers
curl -s -u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/ledgers" \
| python -c "import sys,json; d=json.load(sys.stdin); print(f'Accessible ledgers: {d.get(\"count\",0)}')"
# Check ESS scheduling privilege (for FBDI)
curl -s -w "\nHTTP Status: %{http_code}\n" \
-u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/erpintegrations"
# Verify data scope: list accessible business units
curl -s -u "INT_OIC_FINANCIALS:<password>" \
"https://<instance>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/businessUnits" \
| python -c "import sys,json; d=json.load(sys.stdin); [print(i['BusinessUnitName']) for i in d.get('items',[])]"
Version History & Compatibility
| Release | Date | Status | Security Changes | Migration Notes |
|---|---|---|---|---|
| 25D | 2025-11 | Current | Enhanced REST API data security enforcement | Verify all REST integrations post-upgrade |
| 25C | 2025-08 | Supported | New duty roles for Project Management REST APIs | Add new duty roles if using PPM REST |
| 25B | 2025-05 | Supported | Security Console UI refresh; role comparison tool | No breaking changes |
| 25A | 2025-02 | Supported | None significant | -- |
| 24D | 2024-11 | Supported | Data security enforcement tightened for REST APIs | REST integrations may return empty results |
| 24C | 2024-08 | Supported | New data security requirement for Procurement REST | Add procurement data security policies |
| 24B | 2024-05 | EOL | None significant | Minimum version for current REST features |
When to Use / When Not to Use
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Setting up a new integration with Oracle ERP Cloud | Configuring Oracle IDCS federation | Oracle IDCS documentation |
| Designing minimum-privilege roles for service accounts | Managing end-user (human) role assignments | Oracle HCM Security Implementation Guide |
| Troubleshooting 403 errors or empty API responses | Debugging OIC adapter configuration | OIC adapter documentation |
| Auditing integration user privileges before go-live | Implementing SoD rules | SoD analysis tools (Pathlock, SafePaaS) |
| Migrating integration roles between environments | Setting up OCI IAM policies | OCI IAM documentation |
Important Caveats
- Quarterly updates are mandatory in Oracle Cloud ERP -- you cannot defer them. Every update can modify duty roles, privileges, or data security enforcement. Integration roles must be re-validated after each update.
- This card covers Oracle Fusion Cloud ERP only. Oracle E-Business Suite (EBS), PeopleSoft, and JD Edwards use fundamentally different security models.
- Data security policies use database-level SQL conditions. Complex conditions require careful testing to avoid performance degradation.
- Oracle provides over 3,000 predefined duty roles and 12,000+ function security privileges. Role codes referenced here are current as of Release 25D but may change in future releases.
- SoD analysis is not covered in this card but is critical for integration users spanning multiple modules. Use Oracle Risk Management Cloud or third-party tools for SoD analysis.