---
# === IDENTITY ===
id: business/erp-integration/oracle-erp-cloud-authentication/2026
canonical_question: "What authentication methods does Oracle ERP Cloud support - OAuth 2.0, JWT, IDCS/OCI IAM?"
aliases:
  - "Oracle Fusion Cloud authentication methods"
  - "Oracle ERP Cloud OAuth 2.0 setup"
  - "IDCS vs OCI IAM for Oracle ERP Cloud"
  - "Oracle Fusion REST API authentication"
entity_type: erp_integration
domain: business > erp-integration > oracle-erp-cloud-authentication
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Oracle ERP Cloud (Fusion Cloud Applications)"
    vendor: "Oracle"
    version: "Release 25A (January 2025)"
    edition: "All editions (Enterprise, Standard)"
    deployment: "cloud"
    api_surface: "REST, SOAP"

# === VERIFICATION ===
last_verified: 2026-03-01
confidence: 0.88
version: 1.0
first_published: 2026-03-01

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: volatile
  last_breaking_change: "2022-2024 — IDCS migrated to OCI IAM identity domains; all IDCS instances became identity domains automatically"
  next_review: 2026-08-28
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Basic Auth still works but Oracle strongly recommends OAuth 2.0 — credentials pass in every request header with Basic Auth, creating credential leakage risk"
  - "Access token lifetime defaults to 1 hour (3,600s) for IDCS scopes; max configurable value is bounded by session lifetime (default 8h / 28,800s)"
  - "Refresh tokens default to 7-day lifetime; must request 'offline_access' scope to receive one"
  - "JWT assertion flow requires a PEM-format certificate — CA-signed recommended for production, self-signed acceptable for dev"
  - "Location-Based Access Control (LBAC) can block integration traffic — must allowlist NAT Gateway IPs if LBAC is enabled"
  - "MFA enforcement via sign-on policies can break service account flows if not excluded — service accounts should use OAuth flows that bypass interactive MFA"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Need Salesforce authentication, not Oracle"
    use_instead: "business/erp-integration/salesforce-rest-api/2026"
  - condition: "Need Oracle NetSuite authentication (Token-Based Auth / TBA)"
    use_instead: "business/erp-integration/netsuite-api-capabilities/2026"
  - condition: "Need general OAuth 2.0 implementation patterns (not Oracle-specific)"
    use_instead: "software/patterns/oauth2-client-credentials/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: integration_pattern
    question: "What integration pattern do you need?"
    type: choice
    options:
      - "real-time sync (individual records, <1s latency)"
      - "batch/bulk (scheduled, high volume)"
      - "event-driven (webhook, CDC, platform events)"
      - "file-based (CSV/XML import/export)"
  - key: data_volume
    question: "What's your daily data volume?"
    type: choice
    options:
      - "< 1,000 records/day"
      - "1,000-100,000 records/day"
      - "> 100,000 records/day"
  - key: direction
    question: "What's the data flow direction?"
    type: choice
    options:
      - "inbound (writing to this ERP)"
      - "outbound (reading from this ERP)"
      - "bidirectional sync"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/oracle-erp-cloud-authentication/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-03-01)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "software/patterns/oauth2-client-credentials/2026"
      label: "OAuth2 Client Credentials Flow (general pattern)"
    - id: "software/patterns/jwt-implementation/2026"
      label: "JWT Implementation Patterns"
    - id: "software/patterns/sso-saml-oidc/2026"
      label: "SSO with SAML and OIDC"
  solves: []
  alternative_to: []
  often_confused_with: []

# === SOURCES ===
sources:
  - id: src1
    title: "Configure OAuth Using Oracle Identity Cloud Service or Identity Access Management"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/sales/faaps/Configure_OAuth_Using_Oracle_IDCS_or_IAM.html
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src2
    title: "Configure OAuth Using the Fusion Applications Identity Domain"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/applications-common/25b/oaext/configure-oauth.html
    type: official_docs
    published: 2025-07-01
    reliability: authoritative
  - id: src3
    title: "Authenticating and Working with Oracle Fusion Applications V1 REST APIs"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/authenticate-and-work-with-fusion-v1-api-rest
    type: technical_blog
    published: 2024-03-15
    reliability: high
  - id: src4
    title: "Implement JWT Token Authentication with Fusion Cloud Application (REST/SOAP)"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/implement-jwt-token-authentication-with-fusion-cloud-application-restsoap-extend-in-nodejs-based-applications
    type: technical_blog
    published: 2024-06-01
    reliability: high
  - id: src5
    title: "Oracle Identity Cloud Service: Long Lived OAuth Tokens"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/post/oracle-identity-cloud-service-long-lived-oauth-tokens
    type: technical_blog
    published: 2024-01-15
    reliability: high
  - id: src6
    title: "Securing Oracle Fusion Cloud Applications with Multi-Factor Authentication (MFA)"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/post/securing-oracle-fusion-cloud-applications-with-multifactor-authentication-mfa
    type: technical_blog
    published: 2024-09-01
    reliability: high
  - id: src7
    title: "OCI IAM Identity Domains: What Oracle IDCS Customers Should Expect Post-Migration"
    author: Oracle
    url: https://www.oracle.com/a/ocom/docs/security/what-idcs-customers-should-expect-post-migration.pdf
    type: official_docs
    published: 2024-08-01
    reliability: authoritative
  - id: src8
    title: "Extending Oracle Fusion SaaS with OCI - Security"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/post/extending-oracle-fusion-saas-with-oci-security
    type: technical_blog
    published: 2024-05-01
    reliability: high
---

# Oracle ERP Cloud Authentication

## TL;DR

- **Bottom line**: Oracle ERP Cloud (Fusion Cloud Applications) supports Basic Auth, OAuth 2.0 (client credentials, authorization code, resource owner), and JWT assertion for REST/SOAP API access. OAuth 2.0 with JWT bearer is the recommended approach for server-to-server integrations. [src1]
- **Key limit**: Access tokens default to 1 hour (3,600s) and cannot exceed the session lifetime (default 8 hours / 28,800s). Refresh tokens default to 7 days. [src5]
- **Watch out for**: IDCS has been migrated to OCI IAM identity domains (2022-2024). All documentation referencing "IDCS" still applies but the admin console is now under OCI IAM. Existing IDCS configurations continue to work. [src7]
- **Best for**: Any system-to-system integration with Oracle ERP Cloud REST or SOAP APIs -- financials, procurement, HCM, SCM modules.
- **Authentication**: OAuth 2.0 client credentials (2-legged) or JWT assertion for unattended integrations; authorization code (3-legged) for user-context operations. [src1, src2]

## System Profile

Oracle ERP Cloud (officially "Oracle Fusion Cloud Applications") is Oracle's cloud-native ERP suite covering financials, procurement, project management, supply chain, and HCM. Authentication is handled centrally through OCI IAM identity domains (formerly Oracle Identity Cloud Service / IDCS). All Fusion Cloud Applications are auto-registered as resource applications in the identity domain, and any third-party integrating system must be registered as a confidential client application. [src1]

This card covers authentication for all Oracle Fusion Cloud REST and SOAP APIs across all editions. It does not cover Oracle NetSuite (which uses Token-Based Authentication / TBA) or Oracle E-Business Suite on-premise (which uses Oracle Access Manager). [src2]

| Property | Value |
|---|---|
| **Vendor** | Oracle |
| **System** | Oracle ERP Cloud (Fusion Cloud Applications) Release 25A |
| **API Surface** | REST, SOAP |
| **Current API Version** | Release 25A (quarterly updates: 25A, 25B, 25C, 25D) |
| **Editions Covered** | All Oracle Fusion Cloud editions |
| **Deployment** | Cloud |
| **API Docs URL** | [Oracle Fusion Cloud REST API Docs](https://docs.oracle.com/en/cloud/saas/applications-common/25b/oaext/configure-oauth.html) |
| **Status** | GA |

## API Surfaces & Capabilities

Oracle ERP Cloud exposes two primary API surfaces for integration. Authentication applies uniformly across both. [src2, src3]

| API Surface | Protocol | Best For | Auth Methods | Real-time? | Bulk? |
|---|---|---|---|---|---|
| REST API | HTTPS/JSON | Individual record CRUD, queries, business object operations | Basic Auth, OAuth 2.0, JWT assertion | Yes | Limited (via FBDI) |
| SOAP API | HTTPS/XML | Web service operations, ERP integration events, legacy integrations | Basic Auth, OAuth 2.0, JWT assertion | Yes | Via ERP Integration Service |
| FBDI (File-Based Data Import) | HTTPS + UCM | High-volume batch imports (journals, invoices, POs) | OAuth 2.0 (via UCM upload) | No | Yes |
| BI Publisher Reports | HTTPS/SOAP | Scheduled extracts, report generation | Basic Auth, OAuth 2.0 | No | Yes |

## Rate Limits & Quotas

### Per-Request Limits

| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max request body size | Varies by endpoint | REST API | Typically 10 MB; larger payloads via UCM/FBDI |
| Max concurrent requests | Varies by pod/tenant | All API surfaces | Oracle does not publish fixed concurrent request limits; subject to fair-use throttling |
| Session timeout (default) | 8 hours (28,800s) | All sessions | Configurable in identity domain settings |
| FBDI file size limit | 250 MB | File-Based Data Import | Split larger files into multiple batches |

[src2, src3]

### Rolling / Daily Limits

| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| API call rate limit | Not published (fair-use) | Rolling | Oracle uses adaptive throttling; no fixed published daily cap |
| Burst throttle | HTTP 429 on excessive calls | Per-minute | Back off exponentially when receiving 429 |
| FBDI jobs | Subject to ESS (Enterprise Scheduler) queue | Per-tenant | Shared with other scheduled processes |

[src3, src8]

## Authentication

Oracle ERP Cloud supports four authentication methods for API access. OAuth 2.0 is the recommended approach; Basic Auth remains available but should be avoided for production integrations. [src1, src2]

| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 Client Credentials (2-legged) | Server-to-server, no user context needed | Access: 1h (default, configurable); Refresh: 7 days | Yes (with offline_access scope) | Recommended for integrations. Requires confidential app registration in identity domain. [src1] |
| OAuth 2.0 Authorization Code (3-legged) | User-context operations, interactive flows | Access: 1h; Refresh: 7 days | Yes | User must authenticate interactively. Not suitable for unattended batch jobs. [src2] |
| OAuth 2.0 Resource Owner (Password Grant) | Highly trusted environments only | Access: 1h | No | User credentials passed directly. Avoid in production; does not support MFA. [src3] |
| JWT Assertion (Bearer Token) | Server-to-server with certificate-based trust | Access: 1h (configurable) | New JWT per request | Most secure for machine-to-machine. Requires digital certificate. [src4] |
| Basic Authentication | Quick testing, legacy integrations | Session timeout (8h default) | N/A | Credentials sent in every request (Base64-encoded). High credential leakage risk. [src3] |

### Token Lifetime Configuration

Access token expiry is calculated as `MIN(configured_expiry, remaining_session_lifetime)`. The default IDCS/OCI IAM session lifetime is 8 hours (28,800s). If you configure an access token expiry greater than 8 hours, the resulting token will still expire at or before 28,800 seconds. [src5]

To configure token lifetime:
1. Navigate to OCI IAM Console > Identity Domains > Applications > your confidential app
2. Under Configuration > Resources, set Access Token Expiration
3. For longer-lived tokens, also increase the session lifetime in the identity domain's session settings [src5]

Refresh tokens require adding `offline_access` to the scope parameter when requesting tokens. Default refresh token lifetime is 604,800 seconds (7 days), configurable up to custom values. [src5]

### IDCS to OCI IAM Migration

Oracle began migrating all IDCS instances to OCI IAM identity domains in February 2022, with the process largely complete by mid-2024. Key points for integrators: [src7]

- **No action required**: Existing OAuth configurations, client IDs, client secrets, and certificates all continue to work post-migration
- **Admin console moved**: IDCS admin console is now under OCI Console > Identity & Security > Domains
- **API endpoints unchanged**: Token endpoints (e.g., `https://<idcs-tenant>.identity.oraclecloud.com/oauth2/v1/token`) continue to work
- **Two identity domains post-migration**: A "Default" domain and an "OracleIdentityCloudService" domain (migrated from IDCS)
- **New features available**: Cross-region disaster recovery, improved MFA options, identity domain replication [src7]

### Authentication Gotchas

- **LBAC blocks integration traffic**: If Location-Based Access Control is enabled on your Fusion Applications, you must explicitly allowlist the IP addresses of your integration platform's NAT Gateway. Otherwise you will receive 401 or 403 errors that look like authentication failures but are actually network-layer blocks. [src8]
- **MFA can break service accounts**: If your sign-on policy enforces MFA for all users, service/integration accounts using Resource Owner grant will fail because they cannot complete an interactive MFA challenge. Exclude service accounts from MFA rules, or use Client Credentials / JWT flows that do not require interactive authentication. [src6]
- **Token endpoint varies by domain type**: Post-migration, the token endpoint depends on which identity domain your app is registered in. The "OracleIdentityCloudService" domain retains the old IDCS URL format; the "Default" domain uses the new OCI IAM format. Verify which domain your confidential app belongs to. [src7]
- **Certificate format matters**: JWT assertion flow requires PEM-format certificates. PKCS12 (.p12/.pfx) must be converted. Use a CA-signed certificate for production; self-signed works for development but some security policies may reject it. [src4]
- **Session lifetime caps token lifetime**: Even if you configure a 24-hour access token expiry, the actual token will expire when the session expires (default 8 hours). Both settings must be aligned. [src5]

### Federation with External Identity Providers

Oracle ERP Cloud (via OCI IAM) supports SAML 2.0 federation with external identity providers for SSO: [src7]

| IdP | Protocol | User Provisioning | Notes |
|---|---|---|---|
| Microsoft Entra ID (Azure AD) | SAML 2.0 | Manual or SCIM | Download Entra SAML metadata; configure as IdP in OCI IAM |
| Okta | SAML 2.0 | SCIM (automatic) | Okta as IdP, OCI IAM identity domain as SP; SCIM pushes user changes |
| Any SAML 2.0-compliant IdP | SAML 2.0 | Manual | Upload IdP metadata document to OCI IAM federation settings |

Federation affects interactive (browser-based) authentication only. API-level OAuth flows (Client Credentials, JWT) operate independently of federation configuration. [src7]

## Constraints
<!-- Agents: read this section before recommending any integration approach from this unit.
     These are hard constraints that must not be violated. -->

- **Basic Auth credential exposure**: Basic Authentication sends Base64-encoded username:password in every request header. Any network intercept or log capture exposes credentials. Use OAuth 2.0 instead. [src3]
- **Token lifetime ceiling**: Access tokens cannot exceed the identity domain session lifetime (default 8h). Configuring a longer token expiry has no effect beyond the session boundary. [src5]
- **LBAC allowlisting required**: If LBAC is active, integration platform IPs must be allowlisted or all API calls fail with 401/403. This is a network-level control, not an auth-level one. [src8]
- **Confidential client registration required**: All OAuth flows require registering a confidential application in the identity domain. Public clients (SPAs, mobile apps) cannot be used for ERP Cloud API access. [src1]
- **MFA exclusion for service accounts**: Service/integration accounts must be excluded from MFA enforcement sign-on policies if using Resource Owner grant. Client Credentials and JWT flows are not affected by MFA policies. [src6]
- **Certificate management for JWT**: JWT assertion flow certificates have expiration dates. Monitor and rotate certificates before expiry to prevent integration outages. Oracle does not auto-notify on certificate expiry. [src4]

## Integration Pattern Decision Tree

```
START -- Authenticating with Oracle ERP Cloud
|-- What type of integration?
|   |-- Server-to-server (unattended, scheduled, middleware)
|   |   |-- Can you manage certificates?
|   |   |   |-- YES --> JWT Assertion flow (most secure, no shared secrets)
|   |   |   |-- NO --> OAuth 2.0 Client Credentials (simpler setup)
|   |   |-- Need to act as a specific user?
|   |       |-- YES --> OAuth 2.0 Client Credentials + service user mapping
|   |       |-- NO --> OAuth 2.0 Client Credentials with integration user
|   |-- User-initiated (interactive, delegated access)
|   |   |-- Browser-based UI?
|   |   |   |-- YES --> OAuth 2.0 Authorization Code (3-legged)
|   |   |   |-- NO --> Not recommended; use server-side proxy
|   |   |-- Need SSO with corporate IdP?
|   |       |-- YES --> SAML 2.0 federation + Authorization Code flow
|   |       |-- NO --> Authorization Code flow with identity domain login
|   |-- Quick test / debugging
|       |-- YES --> Basic Auth (dev/test only, never production)
|       |-- NO --> Use OAuth 2.0
|-- Using Oracle Integration Cloud (OIC)?
|   |-- YES --> OAuth configured automatically via Fusion Apps identity domain
|   |-- NO --> Manual confidential app registration required
|-- LBAC enabled on Fusion Apps?
    |-- YES --> Allowlist integration platform NAT Gateway IPs FIRST
    |-- NO --> Proceed with auth setup
```

## Quick Reference

### OAuth 2.0 Token Endpoints

| Endpoint | URL Pattern | Notes |
|---|---|---|
| Token (IDCS-migrated domain) | `https://<tenant>.identity.oraclecloud.com/oauth2/v1/token` | For apps in the OracleIdentityCloudService domain |
| Token (Default domain) | `https://<region>.identity.oraclecloud.com/oauth2/v1/token` | For apps in the Default identity domain |
| Authorize (3-legged) | `https://<tenant>.identity.oraclecloud.com/oauth2/v1/authorize` | Authorization Code flow only |
| JWKS (public keys) | `https://<tenant>.identity.oraclecloud.com/admin/v1/SigningCert/jwk` | For token validation |
| Userinfo | `https://<tenant>.identity.oraclecloud.com/oauth2/v1/userinfo` | Returns authenticated user claims |

[src1, src2]

### Confidential App Registration Checklist

| Step | Action | Where |
|---|---|---|
| 1 | Navigate to Identity Domain | OCI Console > Identity & Security > Domains |
| 2 | Add Application > Confidential Application | Applications > Add Application |
| 3 | Configure grant types | Client Credentials, Authorization Code, JWT Assertion (as needed) |
| 4 | Set allowed scopes | Add Oracle Fusion Apps resource scopes (e.g., `urn:opc:resource:fa:...`) |
| 5 | Upload certificate (JWT only) | Under application > Certificates tab |
| 6 | Note Client ID and Client Secret | Required for token requests |
| 7 | Activate the application | Application must be Active to issue tokens |

[src1, src2]

## Step-by-Step Integration Guide

### 1. Register a Confidential Application in OCI IAM

Create the OAuth client that will authenticate with Oracle ERP Cloud. [src1]

1. Log in to OCI Console > Identity & Security > Domains
2. Select the appropriate identity domain (usually "OracleIdentityCloudService")
3. Click Applications > Add Application > Confidential Application
4. Name the application (e.g., "ERP Integration Client")
5. Under Client Configuration, select the grant types you need (Client Credentials, Authorization Code, or JWT Assertion)
6. Under Resources, add the Oracle Fusion Cloud Applications as an allowed scope
7. Record the Client ID and Client Secret
8. Click Activate to enable the application

**Verify**: In the Applications list, confirm the application shows Status: Active.

### 2. Obtain an Access Token (Client Credentials)

Exchange client credentials for an access token. [src1, src3]

```bash
# Input:  Client ID, Client Secret, Token endpoint URL
# Output: JSON with access_token, token_type, expires_in

curl -X POST \
  "https://<tenant>.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "<CLIENT_ID>:<CLIENT_SECRET>" \
  -d "grant_type=client_credentials&scope=urn:opc:resource:consumer::all"
```

**Verify**: Response contains `"token_type": "Bearer"` and `"expires_in": 3600` (or your configured value).

### 3. Obtain an Access Token (JWT Assertion)

Use a signed JWT to request an access token without sharing a client secret. [src4]

```bash
# Input:  Signed JWT assertion, Token endpoint URL
# Output: JSON with access_token, token_type, expires_in

# Step 1: Generate a JWT with these claims:
# - iss: <CLIENT_ID>
# - sub: <CLIENT_ID>
# - aud: https://<tenant>.identity.oraclecloud.com/oauth2/v1/token
# - exp: current_time + 300 (5 minutes)
# - iat: current_time
# Sign with your private key (RS256 algorithm)

# Step 2: Exchange JWT for access token
curl -X POST \
  "https://<tenant>.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer\
&assertion=<SIGNED_JWT>\
&scope=urn:opc:resource:consumer::all"
```

**Verify**: Response contains `"token_type": "Bearer"`. No client secret was transmitted.

### 4. Call an Oracle ERP Cloud REST API

Use the access token to invoke any Fusion Cloud REST endpoint. [src3]

```bash
# Input:  Access token, Fusion Cloud REST endpoint
# Output: JSON response from Oracle ERP Cloud

curl -X GET \
  "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/invoices" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json"
```

**Verify**: HTTP 200 response with JSON payload. If 401, check token expiry and LBAC allowlisting.

### 5. Implement Token Refresh

For long-running integrations, refresh the access token before it expires. [src5]

```bash
# Input:  Refresh token (obtained by including offline_access scope), Client credentials
# Output: New access_token and refresh_token

curl -X POST \
  "https://<tenant>.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "<CLIENT_ID>:<CLIENT_SECRET>" \
  -d "grant_type=refresh_token&refresh_token=<REFRESH_TOKEN>"
```

**Verify**: New `access_token` and `refresh_token` in response. Update stored tokens.

### 6. Configure MFA Exclusion for Service Accounts

Ensure integration/service accounts are not blocked by MFA sign-on policies. [src6]

1. Navigate to OCI Console > Identity & Security > Domains > Security > Sign-on policies
2. Edit the sign-on policy rule that enforces MFA
3. Add an exclusion condition for the integration user (by username or group membership)
4. Alternatively, create a dedicated sign-on policy rule for service accounts that does not require MFA
5. Ensure the service account rule has higher priority (lower position number) than the MFA-enforcing rule

**Verify**: Authenticate as the service account using Client Credentials flow. Token should be issued without MFA challenge.

## Code Examples

### Python: OAuth 2.0 Client Credentials Token Request

```python
# Input:  Oracle ERP Cloud tenant URL, Client ID, Client Secret
# Output: Access token string for API calls

import requests  # requests>=2.31.0

def get_oracle_erp_token(tenant_url, client_id, client_secret):
    """Obtain OAuth 2.0 access token from Oracle OCI IAM."""
    token_url = f"{tenant_url}/oauth2/v1/token"

    response = requests.post(
        token_url,
        auth=(client_id, client_secret),
        data={
            "grant_type": "client_credentials",
            "scope": "urn:opc:resource:consumer::all"
        },
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        timeout=30  # Oracle token endpoint can be slow
    )
    response.raise_for_status()  # Raises on 4xx/5xx

    token_data = response.json()
    return token_data["access_token"]

# Usage:
# token = get_oracle_erp_token(
#     "https://mytenant.identity.oraclecloud.com",
#     "abc123clientid",
#     "secret456"
# )
```

### Python: JWT Assertion Token Request

```python
# Input:  Private key (PEM), Client ID, Token endpoint
# Output: Access token obtained via JWT assertion

import time
import jwt  # PyJWT>=2.8.0
import requests  # requests>=2.31.0

def get_oracle_erp_token_jwt(
    token_endpoint, client_id, private_key_pem
):
    """Obtain token using JWT assertion (no shared secret)."""
    now = int(time.time())

    # Build JWT claims per Oracle IDCS/OCI IAM spec
    claims = {
        "iss": client_id,
        "sub": client_id,
        "aud": token_endpoint,
        "iat": now,
        "exp": now + 300,  # 5-minute JWT lifetime
    }

    # Sign with RS256 using the private key uploaded to the confidential app
    signed_jwt = jwt.encode(claims, private_key_pem, algorithm="RS256")

    response = requests.post(
        token_endpoint,
        data={
            "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
            "assertion": signed_jwt,
            "scope": "urn:opc:resource:consumer::all",
        },
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        timeout=30,
    )
    response.raise_for_status()
    return response.json()["access_token"]
```

### JavaScript/Node.js: Client Credentials with Token Caching

```javascript
// Input:  Oracle tenant URL, Client ID, Client Secret
// Output: Cached access token with automatic refresh

// node-fetch@3.3.0 or built-in fetch (Node 18+)

class OracleERPAuth {
  constructor(tenantUrl, clientId, clientSecret) {
    this.tokenUrl = `${tenantUrl}/oauth2/v1/token`;
    this.clientId = clientId;
    this.clientSecret = clientSecret;
    this.token = null;
    this.expiresAt = 0;
  }

  async getToken() {
    // Return cached token if still valid (with 60s buffer)
    if (this.token && Date.now() < this.expiresAt - 60000) {
      return this.token;
    }

    const credentials = Buffer.from(
      `${this.clientId}:${this.clientSecret}`
    ).toString("base64");

    const response = await fetch(this.tokenUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        Authorization: `Basic ${credentials}`,
      },
      body: "grant_type=client_credentials&scope=urn:opc:resource:consumer::all",
    });

    if (!response.ok) {
      throw new Error(`Token request failed: ${response.status}`);
    }

    const data = await response.json();
    this.token = data.access_token;
    // expires_in is in seconds; convert to ms timestamp
    this.expiresAt = Date.now() + data.expires_in * 1000;
    return this.token;
  }
}
```

### cURL: Quick Authentication Test

```bash
# Input:  Client ID, Client Secret, Tenant URL
# Output: JSON with access_token confirming auth works

# Test Client Credentials flow
curl -v -X POST \
  "https://<tenant>.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "<CLIENT_ID>:<CLIENT_SECRET>" \
  -d "grant_type=client_credentials&scope=urn:opc:resource:consumer::all"

# Expected response (HTTP 200):
# {
#   "access_token": "eyJ0eXAiOi...",
#   "token_type": "Bearer",
#   "expires_in": 3600
# }

# Test the token against Fusion REST API
curl -X GET \
  "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# Expected: HTTP 200 with API resource listing
```

## Data Mapping

### Authentication Credential Mapping

| Source (Integration Platform) | Target (Oracle OCI IAM) | Type | Transform | Gotcha |
|---|---|---|---|---|
| Client ID | Confidential App Client ID | String | Direct | Must be from the correct identity domain |
| Client Secret | Confidential App Client Secret | String | Direct | Rotate periodically; store in vault, never in code |
| Private Key (PEM) | Certificate uploaded to app | RSA Key | Convert from PKCS12 if needed | Must match the public cert uploaded to the confidential app |
| Scope | `urn:opc:resource:consumer::all` | String | Direct | Or use specific resource scopes for least privilege |
| Grant type | `client_credentials` or `urn:ietf:params:oauth:grant-type:jwt-bearer` | String | Direct | Must match the grant types enabled on the app |

### Data Type Gotchas

- **Token endpoint URL format varies**: IDCS-migrated domains use `<tenant>.identity.oraclecloud.com`; newer domains may use `<region>.identity.oraclecloud.com`. Check your OCI Console for the exact URL. [src7]
- **Scope URN is Oracle-specific**: Unlike standard OAuth scopes (e.g., `openid profile`), Oracle Fusion uses URN-based scopes like `urn:opc:resource:consumer::all`. Using incorrect scope values returns a 400 error with minimal diagnostic information. [src1]
- **Base64 encoding for Basic Auth header**: The `client_id:client_secret` must be Base64-encoded as a single string. Some HTTP clients do this automatically (curl `-u` flag), others require manual encoding. [src3]

## Error Handling & Failure Points

### Common Error Codes

| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 401 Unauthorized | Invalid or expired token | Token expired, wrong credentials, or LBAC blocking | Check token expiry; verify LBAC allowlist; re-authenticate |
| 403 Forbidden | Insufficient permissions | Service user lacks required Fusion Cloud role/privilege | Assign correct application roles to integration user |
| 400 Bad Request | Invalid token request | Wrong grant_type, missing scope, inactive app | Verify grant type enabled on app; check scope URN; ensure app is Active |
| 429 Too Many Requests | Rate throttled | Excessive API calls in short window | Exponential backoff: wait 2^n seconds (max 5 retries) |
| 500 Internal Server Error | Oracle server error | Transient infrastructure issue | Retry with backoff; check Oracle Cloud status page |
| INVALID_CLIENT | Client authentication failed | Wrong Client ID or Secret | Verify credentials; check if app is in correct identity domain |

[src1, src3]

### Failure Points in Production

- **Certificate expiry breaks JWT flow silently**: JWT assertion tokens start failing when the uploaded certificate expires. Oracle does not send expiry notifications. Fix: `Monitor certificate expiry dates; set calendar reminders 30 days before; automate rotation using OCI Certificate Service`. [src4]
- **LBAC false positives after IP change**: Cloud integration platforms (OIC, MuleSoft, Boomi) can change NAT Gateway IPs during maintenance. Fix: `Use IP ranges/CIDR blocks in LBAC allowlist rather than individual IPs; monitor for 401 errors correlating with platform maintenance windows`. [src8]
- **Sign-on policy changes break existing integrations**: An admin enabling MFA for "all users" inadvertently includes service accounts. Fix: `Create a dedicated sign-on policy rule for service accounts (by group membership) positioned above the MFA rule; use Client Credentials or JWT flows which bypass interactive MFA`. [src6]
- **Token endpoint URL mismatch after migration**: Post-IDCS migration, some teams use the old IDCS URL while their app was moved to a different identity domain. Fix: `Verify the app's identity domain in OCI Console; use the token endpoint URL shown in the domain's OAuth configuration`. [src7]
- **Refresh token silent expiry**: Refresh tokens expire after 7 days of non-use by default. Long-idle integrations (e.g., monthly batch jobs) fail silently on the next run. Fix: `For infrequent jobs, request a new token each run instead of relying on refresh tokens; or increase refresh token lifetime in the app configuration`. [src5]

## Anti-Patterns

### Wrong: Hardcoding Basic Auth credentials in integration code

```python
# BAD -- credentials in every request, exposed in logs and network traces
import requests
response = requests.get(
    "https://erp.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/invoices",
    auth=("admin_user", "P@ssw0rd123"),  # Credentials in source code!
    headers={"Content-Type": "application/json"}
)
```

### Correct: Use OAuth 2.0 with credentials from a vault

```python
# GOOD -- token-based auth, credentials stored in vault, token cached
import os, requests

def get_invoices():
    token = get_oracle_erp_token(  # From code example above
        os.environ["ORACLE_TENANT_URL"],
        os.environ["ORACLE_CLIENT_ID"],  # From env/vault
        os.environ["ORACLE_CLIENT_SECRET"],  # From env/vault
    )
    return requests.get(
        "https://erp.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/invoices",
        headers={"Authorization": f"Bearer {token}"},
    )
```

### Wrong: Requesting a new token for every single API call

```python
# BAD -- unnecessary token requests, wastes time and may trigger rate limits
for invoice_id in invoice_ids:
    token = get_oracle_erp_token(tenant, client_id, secret)  # New token every iteration!
    response = requests.get(f"{base_url}/invoices/{invoice_id}",
        headers={"Authorization": f"Bearer {token}"})
```

### Correct: Cache token and reuse until near expiry

```python
# GOOD -- single token reused across calls, refreshed proactively
auth = OracleTokenCache(tenant, client_id, secret)  # Cache with auto-refresh
for invoice_id in invoice_ids:
    token = auth.get_valid_token()  # Returns cached token or refreshes if near expiry
    response = requests.get(f"{base_url}/invoices/{invoice_id}",
        headers={"Authorization": f"Bearer {token}"})
```

### Wrong: Applying MFA to all users without service account exclusion

```
-- BAD sign-on policy configuration:
Rule 1: "All Users" --> Require MFA (no exceptions)
-- Result: Service accounts cannot authenticate via OAuth Resource Owner grant
```

### Correct: Create separate sign-on policy rule for service accounts

```
-- GOOD sign-on policy configuration:
Rule 1 (higher priority): "Integration Service Accounts" group --> Allow, no MFA
Rule 2 (lower priority): "All Users" --> Require MFA
-- Result: Service accounts authenticate normally; human users still require MFA
```

## Common Pitfalls

- **Using Resource Owner grant in production**: The Resource Owner Password Credentials grant passes username/password directly and does not support MFA. It is acceptable only for development/testing. Fix: `Migrate to Client Credentials (2-legged) or JWT Assertion for all production integrations`. [src3]
- **Not configuring token caching**: Each token request adds 200-500ms latency. High-volume integrations that request a new token per API call waste significant time. Fix: `Cache tokens in memory with expiry tracking; refresh proactively 60 seconds before expiry`. [src5]
- **Ignoring LBAC when troubleshooting auth failures**: 401/403 errors from LBAC look identical to authentication failures. Teams spend hours debugging OAuth configuration when the issue is IP allowlisting. Fix: `Check LBAC settings first when receiving unexpected 401/403; test from an allowlisted IP to isolate`. [src8]
- **Wrong identity domain after IDCS migration**: Post-migration, tenants have at least two identity domains. Registering the app in the wrong domain means tokens are valid but lack permissions for Fusion Cloud resources. Fix: `Register confidential apps in the domain that contains Fusion Cloud resource applications (typically "OracleIdentityCloudService")`. [src7]
- **Not rotating client secrets or certificates**: Oracle does not enforce automatic rotation. Leaked credentials remain valid indefinitely until manually rotated. Fix: `Implement a secret rotation schedule (90 days recommended); use OCI Vault for secret storage and rotation automation`. [src4]
- **Assuming sandbox and production use the same identity domain**: Each Oracle Cloud environment (production, test, development) has its own identity domain with separate client registrations. Fix: `Maintain separate OAuth client registrations per environment; use environment variables to switch between them`. [src2]

## Diagnostic Commands

```bash
# Test token endpoint connectivity
curl -v -X POST \
  "https://<tenant>.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -u "<CLIENT_ID>:<CLIENT_SECRET>"

# Decode and inspect a JWT access token (without verification)
echo "<ACCESS_TOKEN>" | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool

# Check token claims (expiry, issuer, audience)
# Look for: "exp" (Unix timestamp), "iss" (issuer URL), "aud" (audience)

# Test Fusion Cloud API access with token
curl -w "\nHTTP Status: %{http_code}\n" \
  -X GET "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# Verify identity domain OpenID configuration (discovery document)
curl "https://<tenant>.identity.oraclecloud.com/.well-known/openid-configuration" \
  | python3 -m json.tool

# Check if LBAC is causing auth failures (test from known-good IP)
# If this works but remote integration fails, LBAC is the issue
curl -X GET "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -w "\nHTTP: %{http_code}, Remote IP: %{remote_ip}\n"
```

## Version History & Compatibility

| Release | Date | Status | Breaking Changes | Migration Notes |
|---|---|---|---|---|
| OCI IAM Identity Domains (GA) | 2022-02 | Current | IDCS admin console moved to OCI Console | All IDCS APIs and endpoints continue to work; admin UI relocated |
| IDCS Region Migration | 2023-03 to 2024-06 | Complete | Automatic region-by-region migration | No integration changes required; tokens and client IDs preserved |
| Identity Domain Replication | 2024-08 | Current | None | New feature: cross-region DR for identity domains |
| Fusion Cloud Release 25A | 2025-01 | Current | None auth-related | Quarterly release; API endpoints unchanged |

[src7]

### Deprecation Policy

Oracle has not announced a formal deprecation date for Basic Authentication on Fusion Cloud REST/SOAP APIs, but all official documentation strongly recommends OAuth 2.0 and positions Basic Auth as legacy. Plan for eventual deprecation. OAuth configurations (Client IDs, secrets, certificates) are preserved across Fusion Cloud quarterly releases. [src1, src2]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Building server-to-server integrations with Oracle ERP Cloud | Need Oracle NetSuite authentication (uses Token-Based Auth) | business/erp-integration/netsuite-api-capabilities/2026 |
| Connecting middleware (OIC, MuleSoft, Boomi) to Fusion Cloud | Need general OAuth 2.0 patterns (not Oracle-specific) | software/patterns/oauth2-client-credentials/2026 |
| Setting up SSO/federation for Oracle ERP Cloud users | Need SAP S/4HANA authentication | business/erp-integration/sap-s4hana-api-capabilities/2026 |
| Migrating from Basic Auth to OAuth 2.0 on Oracle ERP Cloud | Need on-premise Oracle E-Business Suite auth (uses Oracle Access Manager) | N/A -- different product line |

## Important Caveats

- Oracle does not publish fixed API rate limits for Fusion Cloud. Throttling is adaptive and varies by tenant, pod, and load conditions. The 429 response code is your only signal. [src3]
- Token lifetime configuration applies per-application within a single identity domain. Different confidential apps can have different token lifetimes. [src5]
- Post-IDCS migration, some Oracle documentation still references "IDCS" terminology. The underlying functionality is identical in OCI IAM identity domains, but the admin navigation paths have changed. [src7]
- Federation with external IdPs (Azure AD, Okta) affects browser-based SSO only. API-level OAuth flows (Client Credentials, JWT) operate independently and are not affected by federation configuration. [src7]
- Oracle ERP Cloud environments (production, test, development) have completely separate identity domains. OAuth client registrations, certificates, and tokens are not portable across environments. [src2]

## Related Units
<!-- Generated from related_kos frontmatter -->

- [OAuth2 Client Credentials Flow](/software/patterns/oauth2-client-credentials/2026)
- [JWT Implementation Patterns](/software/patterns/jwt-implementation/2026)
- [SSO with SAML and OIDC](/software/patterns/sso-saml-oidc/2026)
