---
# === IDENTITY ===
id: business/erp-integration/oracle-erp-cloud-authentication-patterns/2026
canonical_question: "How do Oracle ERP Cloud authentication patterns work - OAuth 2.0 grant types, SAML, basic auth?"
aliases:
  - "Oracle Fusion Cloud OAuth 2.0 grant type patterns"
  - "Oracle ERP Cloud SAML federation implementation"
  - "Oracle Fusion Cloud certificate-based authentication setup"
  - "Oracle ERP Cloud identity propagation patterns"
entity_type: erp_integration
domain: business > erp-integration > oracle-erp-cloud-authentication-patterns
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Oracle ERP Cloud (Fusion Cloud Applications)"
    vendor: "Oracle"
    version: "Release 25B (April 2025)"
    edition: "All editions (Enterprise, Standard)"
    deployment: "cloud"
    api_surface: "REST, SOAP"

# === VERIFICATION ===
last_verified: 2026-03-09
confidence: 0.88
version: 1.0
first_published: 2026-03-09

# === 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-09-05
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Only confidential applications can be registered for OAuth flows — public clients (SPAs, mobile apps) cannot directly access Fusion Cloud APIs"
  - "JWT assertion requires PEM-format certificate — PKCS12 (.p12/.pfx) must be converted before upload to the identity domain"
  - "Access token lifetime capped by session lifetime: MIN(configured_token_expiry, remaining_session_lifetime) — default session 8h (28,800s)"
  - "SAML federation applies to interactive SSO only — API-level OAuth flows (Client Credentials, JWT) bypass federation entirely"
  - "Location-Based Access Control (LBAC) blocks integration traffic if NAT Gateway IPs are not allowlisted — produces 401/403 indistinguishable from auth failures"
  - "Each Fusion environment (prod, test, dev) has a separate identity domain — OAuth registrations, certificates, and tokens are not portable across environments"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Need basic Oracle ERP Cloud auth overview (which method to choose)"
    use_instead: "business/erp-integration/oracle-erp-cloud-authentication/2026"
  - condition: "Need Salesforce OAuth authentication patterns"
    use_instead: "business/erp-integration/salesforce-oauth-authentication/2026"
  - condition: "Need Oracle NetSuite authentication (Token-Based Auth / TBA)"
    use_instead: "business/erp-integration/netsuite-tba-vs-oauth2/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-patterns/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-03-09)"

# === RELATED UNITS ===
related_kos:
  depends_on:
    - id: "business/erp-integration/oracle-erp-cloud-authentication/2026"
      label: "Oracle ERP Cloud Authentication (overview — which method to choose)"
  related_to:
    - id: "business/erp-integration/oracle-erp-cloud-rest-api-capabilities/2026"
      label: "Oracle ERP Cloud REST API Capabilities"
    - id: "business/erp-integration/oracle-integration-cloud-capabilities/2026"
      label: "Oracle Integration Cloud (OIC) Capabilities"
    - id: "business/erp-integration/erp-authentication-comparison/2026"
      label: "ERP Authentication Methods Comparison (cross-system)"
  solves:
    - id: "business/erp-integration/oracle-oic-vs-mulesoft-oracle-erp/2026"
      label: "OIC vs MuleSoft for Oracle ERP integration"
  alternative_to:
    - id: "business/erp-integration/dynamics-365-authentication/2026"
      label: "Dynamics 365 Authentication Patterns"
    - id: "business/erp-integration/sap-authentication-methods/2026"
      label: "SAP Authentication Methods"
  often_confused_with:
    - id: "business/erp-integration/netsuite-tba-vs-oauth2/2026"
      label: "NetSuite TBA vs OAuth 2.0 (different Oracle product, different auth model)"

# === SOURCES ===
sources:
  - id: src1
    title: "Configure OAuth Using the Fusion Applications Identity Domain"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/applications-common/25c/oaext/configure-oauth.html
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src2
    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: src3
    title: "Identity Propagation from OIC to Fusion SaaS Applications"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/identity-propagation-oic-fusion-saas
    type: technical_blog
    published: 2024-04-15
    reliability: high
  - id: src4
    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: src5
    title: "OCI IAM OAuth Flows Best Practices"
    author: Oracle
    url: https://docs.oracle.com/en-us/iaas/Content/Resources/Assets/whitepapers/oci-iam-oauth-flows-best-practices.pdf
    type: official_docs
    published: 2025-01-01
    reliability: authoritative
  - 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: "Using Azure AD Token to Call Fusion REST APIs"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/post/aad-token-fusion-apis
    type: technical_blog
    published: 2024-07-01
    reliability: high
---

# Oracle ERP Cloud Authentication Patterns

## TL;DR

- **Bottom line**: Oracle Fusion Cloud supports four OAuth 2.0 grant types (client credentials, authorization code, resource owner password, JWT assertion), SAML 2.0 federation for SSO, and Basic Auth as a legacy fallback. JWT assertion with certificate-based trust is the most secure pattern for unattended integrations; client credentials is the most common. [src1]
- **Key limit**: Access tokens default to 3,600 seconds (1 hour), capped by the identity domain session lifetime (default 8 hours). Refresh tokens require the `offline_access` scope and default to 7 days. [src1, src5]
- **Watch out for**: Identity propagation (flowing the end-user identity through middleware to Fusion Cloud) requires specific OAuth configurations -- using the JWT User Assertion security policy in OIC or constructing on-behalf-of flows manually. Getting this wrong means all API calls execute as the integration user, not the actual user. [src3]
- **Best for**: Deep-dive into implementation patterns for each auth flow, certificate lifecycle, SAML federation setup, and multi-environment auth strategies.
- **Authentication**: OAuth 2.0 client credentials for most server-to-server; JWT assertion for zero-secret deployments; authorization code for user-delegated; SAML 2.0 for browser SSO federation. [src1, src2]

## System Profile

Oracle ERP Cloud (Fusion Cloud Applications) centralizes all authentication through OCI IAM identity domains (the successor to Oracle Identity Cloud Service / IDCS). Every Fusion Cloud environment comes with a pre-provisioned identity domain where Fusion Applications are auto-registered as resource applications. Third-party systems and middleware must be registered as confidential client applications within this domain to obtain OAuth tokens. [src1]

This card covers the detailed implementation patterns for each authentication flow. For a high-level overview of which authentication method to choose, see the prerequisite card (oracle-erp-cloud-authentication). This card does not cover Oracle NetSuite (which uses Token-Based Authentication) or Oracle E-Business Suite on-premise. [src4]

| Property | Value |
|---|---|
| **Vendor** | Oracle |
| **System** | Oracle ERP Cloud (Fusion Cloud Applications) Release 25B |
| **API Surface** | REST, SOAP |
| **Current API Version** | Release 25B (quarterly: 25A, 25B, 25C, 25D) |
| **Editions Covered** | All Oracle Fusion Cloud editions |
| **Deployment** | Cloud |
| **API Docs URL** | [Oracle Fusion Cloud OAuth Configuration](https://docs.oracle.com/en/cloud/saas/applications-common/25c/oaext/configure-oauth.html) |
| **Status** | GA |

## API Surfaces & Capabilities

Oracle Fusion Cloud exposes multiple API surfaces. Authentication applies uniformly across all of them -- the same OAuth token works for REST, SOAP, and UCM file upload endpoints. The token's scope and the integration user's Fusion roles determine which API operations are permitted. [src1, src4]

| API Surface | Protocol | Best For | Auth Methods | Token Type | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| REST API (v2) | HTTPS/JSON | Individual record CRUD, business object queries | OAuth 2.0, JWT, Basic Auth | Bearer (access token) | Yes | No |
| SOAP API | HTTPS/XML | Web service operations, ERP Integration Service | OAuth 2.0, JWT, Basic Auth, SAML assertion | SAML token or Bearer | Yes | Via ERP Integration Service |
| UCM (WebCenter Content) | HTTPS | FBDI file upload, report retrieval | OAuth 2.0, Basic Auth | Bearer | No | Yes |
| BI Publisher | HTTPS/SOAP | Scheduled extracts, custom reports | OAuth 2.0, Basic Auth | Bearer | No | Yes |
| Business Events | HTTPS/JSON | Outbound event notifications | OAuth 2.0 (at subscriber) | Bearer (subscriber-side) | Yes | N/A |

[src1, src4]

## Rate Limits & Quotas

### Per-Request Limits

| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max request body size | ~10 MB (varies by endpoint) | REST API | Larger payloads via UCM/FBDI |
| Max concurrent requests | Not published (fair-use) | All API surfaces | Adaptive throttling per tenant/pod |
| Session timeout (default) | 8 hours (28,800s) | All sessions | Configurable in identity domain settings |
| Token request rate | Not published | OAuth token endpoint | Excessive token requests trigger 429 |
| FBDI file size limit | 250 MB | File-Based Data Import | Split larger files into multiple batches |

[src4, src5]

### 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 cap |
| Burst throttle | HTTP 429 on excessive calls | Per-minute | Back off exponentially on 429 |
| Token endpoint rate | Fair-use throttling | Per-minute | Cache tokens to avoid hitting limits |
| FBDI/ESS jobs | Subject to Enterprise Scheduler queue | Per-tenant | Shared with other scheduled processes |

[src4, src5]

## Authentication

This section provides detailed implementation patterns for each Oracle ERP Cloud authentication flow. [src1]

| Flow | Grant Type | Use When | Token Lifetime | Refresh? | Security Level |
|---|---|---|---|---|---|
| Client Credentials (2-legged) | `client_credentials` | Server-to-server, no user context | Access: 1h (default); Refresh: 7d | Yes (with `offline_access`) | High -- no user credentials exposed |
| Authorization Code (3-legged) | `authorization_code` | User-context operations, delegated access | Access: 1h; Refresh: 7d | Yes | High -- user authenticates interactively |
| Resource Owner Password | `password` | Legacy, testing only | Access: 1h | No | Low -- credentials passed directly |
| JWT Assertion | `urn:ietf:params:oauth:grant-type:jwt-bearer` | Server-to-server, certificate trust | Access: 1h (configurable) | New JWT per request | Highest -- no shared secrets |
| SAML 2.0 Bearer Assertion | `urn:ietf:params:oauth:grant-type:saml2-bearer` | Cross-domain identity propagation | Access: 1h | No | High -- requires IdP trust |
| Basic Authentication | N/A (HTTP header) | Quick testing only | Session timeout (8h) | N/A | Lowest -- credentials in every request |

[src1, src2, src4]

### Pattern 1: Client Credentials (2-Legged OAuth)

The most common pattern for server-to-server integrations. The confidential application authenticates using its client ID and client secret. All API calls execute under the integration user's identity (no end-user context). [src1]

**Setup requirements:**
1. Register a confidential application in the Fusion Apps identity domain
2. Enable the "Client Credentials" grant type on the application
3. Configure allowed scopes (typically `urn:opc:resource:consumer::all` for full Fusion access)
4. Assign the desired Fusion application roles to the integration user
5. Activate the application

**Token request flow:**
- POST to `https://<domain>.identity.oraclecloud.com/oauth2/v1/token`
- Authorization header: Basic Base64(`client_id:client_secret`)
- Body: `grant_type=client_credentials&scope=urn:opc:resource:consumer::all`
- Response: `{ "access_token": "...", "token_type": "Bearer", "expires_in": 3600 }`

**When to use**: Middleware-to-ERP integrations, scheduled batch jobs, any unattended process that does not need user-level audit trail. [src1]

### Pattern 2: JWT Assertion (Certificate-Based)

Most secure pattern for machine-to-machine integrations. Instead of a shared client secret, the application signs a JWT with a private key. The corresponding public certificate is uploaded to the confidential application in the identity domain. [src2]

**Setup requirements:**
1. Generate an RSA key pair (2048-bit minimum, 4096-bit recommended)
2. Register a confidential application and enable "JWT Assertion" grant type
3. Upload the public certificate (PEM format) to the application's Certificates tab
4. Store the private key securely (HSM, vault, never in source code)
5. Activate the application

**JWT claims required:**
- `iss`: Client ID of the confidential application
- `sub`: Client ID (for app-level) or username (for user-level identity propagation)
- `aud`: Token endpoint URL
- `iat`: Current timestamp (seconds since epoch)
- `exp`: Expiry timestamp (recommend 300 seconds from `iat`)

**Token request flow:**
- POST to `https://<domain>.identity.oraclecloud.com/oauth2/v1/token`
- Body: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<SIGNED_JWT>&scope=urn:opc:resource:consumer::all`
- No Authorization header needed (the JWT itself authenticates the client)

**When to use**: High-security environments, zero-trust architectures, any deployment where you cannot safely store a client secret (e.g., containerized workloads using mounted key files). [src2, src5]

### Pattern 3: Authorization Code (3-Legged OAuth)

Used when the application needs to act on behalf of a specific user. Requires interactive browser-based authentication. Not suitable for unattended batch processing. [src1]

**Setup requirements:**
1. Register a confidential application with "Authorization Code" grant type enabled
2. Configure a redirect URI (callback URL) in the application settings
3. Optionally enable PKCE (Proof Key for Code Exchange) for additional security

**Flow:**
1. Redirect user to: `https://<domain>.identity.oraclecloud.com/oauth2/v1/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=<CALLBACK>&scope=urn:opc:resource:consumer::all`
2. User authenticates (SSO/federation applies here if configured)
3. Identity domain redirects to callback URL with `?code=<AUTH_CODE>`
4. Exchange code for tokens: POST to token endpoint with `grant_type=authorization_code&code=<AUTH_CODE>&redirect_uri=<CALLBACK>`
5. Response includes access_token, refresh_token (if `offline_access` scope requested), and id_token

**When to use**: Custom portals, internal tools that need user-level audit trails, any application where end users interact with Fusion Cloud data through a custom UI. [src1]

### Pattern 4: SAML 2.0 Federation for SSO

SAML federation enables browser-based Single Sign-On where users authenticate against an external Identity Provider (Azure AD, Okta, ADFS, PingFederate) and gain access to Oracle Fusion Cloud without separate credentials. [src6, src7]

**Setup overview:**
1. Configure the external IdP as a SAML Identity Provider in the OCI IAM identity domain
2. Upload the IdP's SAML metadata document (or manually configure SSO URL, entity ID, signing certificate)
3. Map IdP user attributes to OCI IAM identity domain attributes (NameID, email, groups)
4. Configure Fusion Applications to use the identity domain as the authentication source
5. Enable JIT (Just-In-Time) provisioning if you want users auto-created on first login

**Critical note**: SAML federation applies only to interactive browser-based authentication. API-level OAuth flows (Client Credentials, JWT Assertion) are completely independent of federation configuration and bypass the external IdP entirely. [src6, 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 identity domain |
| Okta | SAML 2.0 | SCIM (automatic) | Okta as IdP, identity domain as SP; SCIM pushes user lifecycle changes |
| PingFederate | SAML 2.0 | Manual | Export PingFederate metadata; import into identity domain |
| ADFS | SAML 2.0 | Manual or DirSync | Export ADFS federation metadata XML |
| Any SAML 2.0 IdP | SAML 2.0 | Manual | Upload IdP metadata document to identity domain federation settings |

[src6, src7]

### Pattern 5: Identity Propagation Through Middleware

When Oracle Integration Cloud (OIC) or another middleware platform calls Fusion Cloud APIs, you often need the end-user identity (not the integration user) to flow through for audit and security purposes. [src3]

**OIC identity propagation:**
- OIC uses the OAuth JWT User Assertion security policy when invoking Fusion Cloud REST APIs
- The OIC connection is configured with OAuth using the Fusion Apps identity domain
- When a user triggers an integration via a Fusion Business Event, the user's identity is carried in the JWT assertion
- Fusion Cloud API calls execute under the triggering user's permissions, not the OIC service account

**Manual identity propagation (non-OIC middleware):**
1. User authenticates to your middleware using their corporate credentials
2. Middleware obtains a JWT assertion token with `sub` set to the user's identity
3. JWT is signed with the private key registered in the confidential application
4. Token request includes the user-scoped JWT assertion
5. Resulting access token carries the user identity for Fusion Cloud audit trail

**When to use**: Any integration where regulatory or compliance requirements demand user-level audit trails (SOX compliance, financial approvals, procurement workflows). [src3]

### Pattern 6: External IdP Token Exchange (Azure AD)

For organizations using Microsoft Entra ID (Azure AD) as their primary identity platform, Oracle supports exchanging Azure AD tokens for Oracle access tokens without requiring users to re-authenticate against the Oracle identity domain. [src7]

**Flow:**
1. Application obtains an Azure AD access token (via MSAL or similar)
2. Configure trust between the OCI IAM identity domain and the Azure AD tenant
3. Exchange the Azure AD token for an Oracle access token using the token exchange grant type
4. Use the Oracle access token to call Fusion Cloud REST APIs

**Setup requirements:**
- Register Azure AD as a Social Identity Provider in the OCI IAM identity domain
- Configure attribute mapping between Azure AD claims and Oracle identity attributes
- Register a confidential application with token exchange capabilities

**When to use**: Microsoft-centric environments where users already have Azure AD tokens, and you want to call Oracle Fusion APIs without forcing a separate Oracle login flow. [src7]

### Authentication Gotchas

- **JWT `exp` clock skew**: Oracle identity domains tolerate up to 5 minutes of clock skew on JWT assertions. If your server clock drifts beyond 5 minutes, token requests fail with a cryptic `invalid_grant` error. Use NTP to synchronize clocks. [src2]
- **Certificate chain requirements**: For production JWT flows, some Oracle environments require the full certificate chain (not just the leaf certificate) to be uploaded. If token requests fail with `invalid_client` after uploading only the leaf cert, upload the chain file. [src2]
- **Scope format is Oracle-specific**: Oracle uses URN-based scopes (`urn:opc:resource:consumer::all`), not the standard `openid profile email` format. Using incorrect scope values returns a 400 error with minimal diagnostic detail. [src1]
- **Token endpoint URL varies by domain type**: Post-IDCS migration, the URL depends on which identity domain the app is in. IDCS-migrated domains use `<tenant>.identity.oraclecloud.com`; default domains use the regional format. [src1, src5]
- **SAML NameID format mismatch**: If the external IdP sends a NameID format (e.g., email) that does not match the expected format in the identity domain mapping, SSO silently fails or creates duplicate users. Verify NameID format alignment during setup. [src6]

## Constraints
<!-- Agents: read this section before recommending any integration approach from this unit.
     These are hard constraints that must not be violated. -->

- **Confidential clients only**: All OAuth flows require registering a confidential application. Public clients (SPAs, mobile apps) cannot directly access Fusion Cloud APIs. Mobile apps must proxy through a backend service. [src1]
- **Token lifetime ceiling**: Access tokens cannot exceed the identity domain session lifetime (default 8h / 28,800s). Configuring a 24-hour token expiry produces tokens that still expire at the session boundary. Both settings must be aligned. [src5]
- **LBAC blocks silently**: Location-Based Access Control produces 401/403 errors indistinguishable from authentication failures. If LBAC is active, integration platform IPs must be allowlisted in the Fusion Applications security configuration. [src4]
- **MFA breaks password-grant flows**: Sign-on policies enforcing MFA for all users will block service accounts using the Resource Owner Password grant. Service accounts must be excluded from MFA rules, or use Client Credentials / JWT flows. [src6]
- **Certificate management burden**: JWT assertion certificates expire. Oracle does not send expiry notifications. Failure to rotate before expiry causes silent integration failure. Monitor and rotate proactively. [src2]
- **Environment isolation**: Each Fusion Cloud environment (production, test, development) has its own identity domain. OAuth registrations, certificates, and tokens are not portable. Maintain separate registrations per environment. [src1]
- **SAML is browser-only**: SAML federation has no effect on API-level OAuth flows. Do not attempt to use SAML assertions directly with REST APIs unless using the SAML Bearer Assertion grant type through the token endpoint. [src6, src7]

## Integration Pattern Decision Tree

```
START -- Choosing an Oracle ERP Cloud authentication pattern
|-- What type of client?
|   |-- Server/backend (unattended)
|   |   |-- Can you manage certificates and a PKI lifecycle?
|   |   |   |-- YES --> Pattern 2: JWT Assertion (most secure, no shared secrets)
|   |   |   |-- NO --> Pattern 1: Client Credentials (simpler, uses client secret)
|   |   |-- Do you need user-level audit trail?
|   |       |-- YES --> Pattern 5: Identity Propagation (JWT sub=user)
|   |       |-- NO --> Pattern 1: Client Credentials with integration user
|   |-- Browser-based (user-interactive)
|   |   |-- Do users have existing corporate IdP credentials?
|   |   |   |-- YES, Azure AD --> Pattern 6: Azure AD Token Exchange
|   |   |   |-- YES, Okta/ADFS/Other --> Pattern 4: SAML Federation + Pattern 3
|   |   |   |-- NO --> Pattern 3: Authorization Code (direct identity domain login)
|   |   |-- Need long-lived offline access?
|   |       |-- YES --> Pattern 3 with offline_access scope (refresh tokens)
|   |       |-- NO --> Pattern 3 standard
|   |-- Middleware (OIC, MuleSoft, Boomi)
|   |   |-- Using OIC within same identity domain?
|   |   |   |-- YES --> OAuth auto-configured via identity domain (trust pre-established)
|   |   |   |-- NO --> Manual confidential app registration + Pattern 1 or 2
|   |   |-- Need identity propagation through middleware?
|   |       |-- YES --> Pattern 5: JWT User Assertion security policy
|   |       |-- NO --> Pattern 1: Client Credentials
|   |-- Quick test / debugging
|       |-- Pattern 6 (Basic Auth) -- dev/test only, never production
|-- Is LBAC enabled on Fusion Applications?
|   |-- YES --> Allowlist integration platform NAT Gateway IPs FIRST
|   |-- NO --> Proceed with auth pattern setup
|-- Multi-environment (prod/test/dev)?
    |-- YES --> Separate confidential app registration per environment
    |-- NO --> Single registration sufficient
```

## Quick Reference

### OAuth 2.0 Grant Types Comparison

| Grant Type | Client Secret Required | User Interaction | Refresh Token | MFA Compatible | Production Ready |
|---|---|---|---|---|---|
| Client Credentials | Yes | No | Yes (with `offline_access`) | N/A (no user) | Yes |
| JWT Assertion | No (uses certificate) | No | No (new JWT per request) | N/A (no user) | Yes (recommended) |
| Authorization Code | Yes | Yes (browser redirect) | Yes | Yes | Yes |
| Authorization Code + PKCE | No (uses code verifier) | Yes (browser redirect) | Yes | Yes | Yes |
| Resource Owner Password | Yes | No (credentials in request) | No | No (incompatible) | No (legacy only) |
| SAML Bearer Assertion | Yes | No (pre-obtained SAML) | No | Depends on IdP | Yes (specialized) |

[src1, src5]

### Token Endpoint Reference

| Endpoint | URL Pattern | Purpose |
|---|---|---|
| Token (IDCS-migrated) | `https://<tenant>.identity.oraclecloud.com/oauth2/v1/token` | Apps in OracleIdentityCloudService domain |
| Token (Default domain) | `https://<region>.identity.oraclecloud.com/oauth2/v1/token` | Apps in Default identity domain |
| Authorize | `https://<domain>.identity.oraclecloud.com/oauth2/v1/authorize` | Authorization Code flow initiation |
| JWKS | `https://<domain>.identity.oraclecloud.com/admin/v1/SigningCert/jwk` | Token validation / public key retrieval |
| Userinfo | `https://<domain>.identity.oraclecloud.com/oauth2/v1/userinfo` | Authenticated user claims |
| OpenID Discovery | `https://<domain>.identity.oraclecloud.com/.well-known/openid-configuration` | Auto-discovery of all endpoints |
| SAML Metadata | `https://<domain>.identity.oraclecloud.com/fed/v1/metadata` | SP metadata for SAML federation |

[src1, src4]

### Certificate Lifecycle Checklist

| Step | Action | Frequency | Owner |
|---|---|---|---|
| 1 | Generate RSA key pair (4096-bit) | Once per certificate lifecycle | Security team |
| 2 | Upload public cert to confidential app | Once per certificate lifecycle | IAM admin |
| 3 | Store private key in vault/HSM | Once per certificate lifecycle | Security team |
| 4 | Monitor certificate expiry date | Monthly (automated) | Operations |
| 5 | Rotate certificate 30 days before expiry | Per certificate lifecycle (typically 1-2 years) | Security team |
| 6 | Upload new certificate to confidential app | At rotation time | IAM admin |
| 7 | Update private key reference in integration | At rotation time | Integration team |
| 8 | Revoke old certificate after grace period | 7 days post-rotation | IAM admin |

[src2, src5]

## Step-by-Step Integration Guide

### 1. Register a Confidential Application in OCI IAM

Create the OAuth client that all patterns depend on. [src1]

```bash
# Navigate in OCI Console:
# Identity & Security > Domains > [Your Fusion Apps Domain] > Applications > Add Application

# Select: Confidential Application
# Name: "ERP Integration - [Your System Name]"
# Description: "[Integration purpose]"

# Client Configuration:
# - Allowed Grant Types: select based on your pattern:
#   Pattern 1: Client Credentials
#   Pattern 2: JWT Assertion
#   Pattern 3: Authorization Code (+ add Redirect URL)
#   Combination: select multiple as needed

# Resource Configuration:
# - Add scope: urn:opc:resource:consumer::all
#   (or specific Oracle Fusion resource app scopes for least-privilege)

# Record: Client ID and Client Secret
# Click: Activate
```

**Verify**: Applications list shows Status: Active. Client ID is a UUID-format string.

### 2. Obtain Client Credentials Token

Exchange client credentials for an access token (Pattern 1). [src1, src4]

```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"

# For refresh token support, add offline_access scope:
# -d "grant_type=client_credentials&scope=urn:opc:resource:consumer::all offline_access"
```

**Verify**: Response contains `"token_type": "Bearer"` and `"expires_in": 3600`.

### 3. Generate and Use JWT Assertion

Create a signed JWT and exchange it for an access token (Pattern 2). [src2]

```bash
# Step 1: Generate key pair (one-time)
openssl genrsa -out private_key.pem 4096
openssl req -new -x509 -key private_key.pem -out public_cert.pem -days 730 \
  -subj "/CN=ERP Integration/O=YourOrg"

# Step 2: Upload public_cert.pem to confidential app > Certificates tab

# Step 3: Generate JWT (using Python or similar)
# Claims: iss=CLIENT_ID, sub=CLIENT_ID, aud=TOKEN_ENDPOINT, exp=now+300

# Step 4: 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 `"access_token"` without sending any client secret.

### 4. Configure SAML 2.0 Federation

Set up SSO with an external Identity Provider (Pattern 4). [src6, src7]

```bash
# In OCI Console:
# 1. Identity & Security > Domains > [Fusion Apps Domain] > Security > Identity Providers
# 2. Add SAML Identity Provider
# 3. Upload IdP metadata XML (from Azure AD, Okta, ADFS, etc.)
#    - Or manually enter: SSO URL, Entity ID, Signing Certificate
# 4. Configure NameID mapping:
#    - NameID Format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
#    - Map to: User email in identity domain
# 5. Enable JIT Provisioning (optional):
#    - Maps IdP attributes to identity domain user attributes
#    - Auto-creates users on first SSO login
# 6. Set IdP as default for the domain (optional)
# 7. Test with IdP-initiated SSO URL
```

**Verify**: User can access Fusion Cloud Applications via IdP login page without entering Oracle credentials.

### 5. Implement Token Caching and Refresh

Prevent excessive token requests for long-running integrations. [src5]

```python
# Input:  Token endpoint, Client credentials or JWT
# Output: Cached token with automatic refresh

import time
import threading
import requests  # requests>=2.31.0

class OracleTokenManager:
    """Thread-safe token manager with proactive refresh."""

    def __init__(self, token_url, client_id, client_secret):
        self.token_url = token_url
        self.client_id = client_id
        self.client_secret = client_secret
        self._token = None
        self._expires_at = 0
        self._lock = threading.Lock()

    def get_token(self):
        """Return valid token, refreshing if within 60s of expiry."""
        with self._lock:
            if self._token and time.time() < self._expires_at - 60:
                return self._token
            return self._refresh()

    def _refresh(self):
        resp = requests.post(
            self.token_url,
            auth=(self.client_id, self.client_secret),
            data={
                "grant_type": "client_credentials",
                "scope": "urn:opc:resource:consumer::all",
            },
            headers={"Content-Type": "application/x-www-form-urlencoded"},
            timeout=30,
        )
        resp.raise_for_status()
        data = resp.json()
        self._token = data["access_token"]
        self._expires_at = time.time() + data["expires_in"]
        return self._token
```

**Verify**: Multiple calls to `get_token()` within the token lifetime return the cached token without hitting the endpoint.

### 6. Set Up Identity Propagation

Configure middleware to flow end-user identity to Fusion Cloud. [src3]

```bash
# For OIC (Oracle Integration Cloud):
# 1. Connection > Oracle ERP Cloud adapter > configure with OAuth
# 2. Security Policy: "OAuth JWT User Assertion"
# 3. Identity domain: select the Fusion Apps identity domain
# 4. OIC extracts the triggering user's identity from the business event
# 5. JWT assertion contains sub=<end_user_login>
# 6. Fusion Cloud API executes under the end user's permissions

# For manual identity propagation (non-OIC):
# 1. Obtain end-user identity from your authentication layer
# 2. Build JWT with sub=<end_user_login> (instead of sub=<client_id>)
# 3. Sign JWT with the private key registered in the confidential app
# 4. Exchange JWT for token -- resulting token carries user identity
# 5. Fusion Cloud audit trail shows the end user, not the integration user
```

**Verify**: Check Fusion Cloud audit trail (Security > Audit Reports) -- API calls should show the end user's username, not the integration service account.

## Code Examples

### Python: JWT Assertion with Certificate-Based Auth

```python
# Input:  Private key PEM file, Client ID, Token endpoint
# Output: Access token obtained via JWT assertion (no shared secret)

import time
import jwt  # PyJWT>=2.8.0
import requests  # requests>=2.31.0

def get_oracle_token_jwt(token_url, client_id, private_key_path):
    """Obtain Oracle access token using JWT assertion."""
    with open(private_key_path, "r") as f:
        private_key = f.read()

    now = int(time.time())
    claims = {
        "iss": client_id,          # Issuer = confidential app client ID
        "sub": client_id,          # Subject = same for app-level auth
        "aud": token_url,          # Audience = token endpoint
        "iat": now,                # Issued at
        "exp": now + 300,          # Expires in 5 minutes
    }

    signed_jwt = jwt.encode(claims, private_key, algorithm="RS256")

    resp = requests.post(
        token_url,
        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,
    )
    resp.raise_for_status()
    return resp.json()["access_token"]
```

### JavaScript/Node.js: Authorization Code Flow with PKCE

```javascript
// Input:  Client ID, Redirect URI, Token endpoint, Authorization endpoint
// Output: Access token obtained via authorization code + PKCE

// crypto (built-in), node-fetch@3.3.0 or built-in fetch (Node 18+)
import crypto from "crypto";

function generatePKCE() {
  // Generate code verifier (43-128 chars, URL-safe)
  const verifier = crypto.randomBytes(32).toString("base64url");
  // Generate code challenge (S256)
  const challenge = crypto
    .createHash("sha256")
    .update(verifier)
    .digest("base64url");
  return { verifier, challenge };
}

function getAuthorizationURL(authEndpoint, clientId, redirectUri, pkce) {
  const params = new URLSearchParams({
    response_type: "code",
    client_id: clientId,
    redirect_uri: redirectUri,
    scope: "urn:opc:resource:consumer::all offline_access",
    code_challenge: pkce.challenge,
    code_challenge_method: "S256",
  });
  return `${authEndpoint}?${params}`;
}

async function exchangeCodeForToken(
  tokenEndpoint, clientId, clientSecret, code, redirectUri, codeVerifier
) {
  const credentials = Buffer.from(
    `${clientId}:${clientSecret}`
  ).toString("base64");

  const resp = await fetch(tokenEndpoint, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      Authorization: `Basic ${credentials}`,
    },
    body: new URLSearchParams({
      grant_type: "authorization_code",
      code,
      redirect_uri: redirectUri,
      code_verifier: codeVerifier,
    }),
  });

  if (!resp.ok) throw new Error(`Token exchange failed: ${resp.status}`);
  return resp.json(); // { access_token, refresh_token, expires_in, ... }
}
```

### cURL: Test Each Authentication Pattern

```bash
# Input:  Credentials per pattern, Token endpoint
# Output: Access token confirming each pattern works

# --- Pattern 1: Client Credentials ---
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"

# Expected: { "access_token": "eyJ...", "token_type": "Bearer", "expires_in": 3600 }

# --- Pattern 2: JWT Assertion ---
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"

# Expected: same response shape, no client secret transmitted

# --- Verify token works against Fusion Cloud ---
curl -X GET \
  "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -w "\nHTTP Status: %{http_code}\n"

# Expected: HTTP 200 with API resource listing
```

## Data Mapping

### Authentication Configuration Mapping

| Configuration Element | OCI IAM Location | Format | Required For | Gotcha |
|---|---|---|---|---|
| Client ID | Confidential App > General | UUID string | All OAuth flows | Must be from the correct identity domain |
| Client Secret | Confidential App > General | String | Client Credentials, Auth Code | Rotate every 90 days; store in vault |
| Token endpoint URL | Domain > Overview > Domain URL + `/oauth2/v1/token` | URL | All OAuth flows | Varies between IDCS-migrated and Default domains |
| Redirect URI | Confidential App > Client Configuration | URL | Authorization Code only | Must match exactly (including trailing slash) |
| Certificate (PEM) | Confidential App > Certificates | PEM file | JWT Assertion only | Upload full chain for production |
| Scope | Confidential App > Resources | URN string | All OAuth flows | `urn:opc:resource:consumer::all` or specific |
| SAML Metadata | Security > Identity Providers | XML file | SAML Federation only | Download fresh from IdP before each setup |

[src1, src2]

### Data Type Gotchas

- **Token endpoint URL format inconsistency**: IDCS-migrated domains keep the `<tenant>.identity.oraclecloud.com` format; newer Default domains use `<region>.identity.oraclecloud.com`. The OpenID Discovery endpoint (`/.well-known/openid-configuration`) is the authoritative source for the correct token URL. [src1]
- **Scope URN is not standard OAuth**: Oracle uses `urn:opc:resource:consumer::all` rather than standard scopes like `openid profile`. Sending standard scopes returns a 400 error. [src1]
- **JWT `exp` claim precision**: Oracle accepts seconds-precision Unix timestamps only. Millisecond timestamps cause `invalid_grant` errors. [src2]
- **Certificate format conversion**: Oracle requires PEM format. To convert from PKCS12: `openssl pkcs12 -in cert.p12 -out cert.pem -nodes`. [src2]

## Error Handling & Failure Points

### Common Error Codes

| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 400 Bad Request | Invalid token request | Wrong grant_type, missing scope, inactive app, malformed JWT | Verify grant type is enabled on the app; check scope URN; ensure app is Active; validate JWT structure |
| 401 Unauthorized | Invalid or expired token / LBAC block | Token expired, wrong credentials, LBAC blocking, wrong domain | Check token expiry; verify LBAC allowlist; confirm correct identity domain |
| 403 Forbidden | Insufficient permissions | Integration user lacks Fusion roles/privileges | Assign required application roles to the user in Fusion Cloud |
| 429 Too Many Requests | Rate throttled | Excessive API or token requests | Exponential backoff: wait 2^n seconds (max 5 retries); cache tokens |
| `invalid_grant` | JWT assertion rejected | Expired JWT, clock skew >5 min, wrong audience, bad signature | Sync clocks via NTP; verify aud matches token endpoint; check certificate match |
| `invalid_client` | Client authentication failed | Wrong Client ID/Secret, inactive app, certificate mismatch | Verify credentials; check app status; upload correct certificate chain |
| `invalid_scope` | Scope not allowed | Scope not configured on the confidential app | Add the scope in the app's resource configuration |
| `unauthorized_client` | Grant type not enabled | App does not have the requested grant type enabled | Enable the grant type in the confidential app settings |

[src1, src4, src5]

### 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: `Set up automated certificate expiry monitoring (e.g., OCI Events + Notifications); rotate certificates 30 days before expiry; maintain a certificate rotation runbook`. [src2]
- **LBAC false positives after infrastructure changes**: Cloud platforms (OIC, MuleSoft, Boomi) can change NAT Gateway IPs during maintenance or scaling events. Fix: `Use CIDR blocks in LBAC allowlist; subscribe to your iPaaS provider's IP change notifications; monitor for sudden 401 spikes correlating with platform maintenance`. [src4]
- **Sign-on policy change breaks 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; document which accounts are service accounts`. [src6]
- **Token endpoint URL mismatch after IDCS migration**: Some teams hardcode the old IDCS URL while their app was migrated to a different domain. Fix: `Use the OpenID Discovery endpoint to dynamically resolve the correct token URL; never hardcode token endpoints`. [src1]
- **Redirect URI mismatch in Authorization Code flow**: A trailing slash difference or HTTP vs HTTPS mismatch causes the flow to fail with a generic error. Fix: `Copy the redirect URI directly from your application into the OCI IAM configuration; verify with an exact string match`. [src1]
- **Refresh token silent expiry**: Refresh tokens expire after 7 days of non-use. Monthly batch jobs fail silently. Fix: `For infrequent jobs, request a new token each run instead of relying on refresh tokens; or increase refresh token lifetime in app configuration`. [src5]

## Anti-Patterns

### Wrong: Using Basic Auth for production integrations

```python
# BAD -- credentials sent 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=("integration_user", "P@ssw0rd"),  # Credentials in source code!
)
```

### Correct: Use OAuth 2.0 with vault-stored credentials

```python
# GOOD -- token-based auth, credentials from vault, token cached
import os
import requests

token_mgr = OracleTokenManager(
    os.environ["ORACLE_TOKEN_URL"],
    os.environ["ORACLE_CLIENT_ID"],     # From vault/env
    os.environ["ORACLE_CLIENT_SECRET"], # From vault/env
)

response = requests.get(
    "https://erp.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest/invoices",
    headers={"Authorization": f"Bearer {token_mgr.get_token()}"},
)
```

### Wrong: Requesting a new token for every API call

```python
# BAD -- unnecessary token requests, adds 200-500ms latency per call
for invoice_id in invoice_ids:  # 1000 invoices = 1000 token requests
    token = get_fresh_token(endpoint, client_id, secret)
    requests.get(f"{base}/invoices/{invoice_id}",
                 headers={"Authorization": f"Bearer {token}"})
```

### Correct: Cache token and reuse until near expiry

```python
# GOOD -- one token request per hour, reused across all calls
token_mgr = OracleTokenManager(endpoint, client_id, secret)
for invoice_id in invoice_ids:
    token = token_mgr.get_token()  # Returns cached or refreshes if <60s left
    requests.get(f"{base}/invoices/{invoice_id}",
                 headers={"Authorization": f"Bearer {token}"})
```

### Wrong: Hardcoding token endpoint URLs

```python
# BAD -- breaks when IDCS migrates or domain configuration changes
TOKEN_URL = "https://idcs-abc123.identity.oraclecloud.com/oauth2/v1/token"
```

### Correct: Use OpenID Discovery to resolve endpoints dynamically

```python
# GOOD -- resilient to endpoint changes, always uses correct URL
import requests

def discover_token_endpoint(domain_url):
    disco = requests.get(
        f"{domain_url}/.well-known/openid-configuration"
    ).json()
    return disco["token_endpoint"]

TOKEN_URL = discover_token_endpoint(os.environ["ORACLE_DOMAIN_URL"])
```

### Wrong: Sharing one certificate across all environments

```bash
# BAD -- compromised dev certificate exposes production
# Using the same key pair for dev, test, and prod confidential apps
```

### Correct: Separate certificates per environment with distinct key pairs

```bash
# GOOD -- each environment has its own key pair and certificate
# Production: prod_private_key.pem / prod_cert.pem (CA-signed, 2-year)
# Test:       test_private_key.pem / test_cert.pem (self-signed, 1-year)
# Dev:        dev_private_key.pem  / dev_cert.pem  (self-signed, 1-year)

# Generate per-environment key pairs:
openssl genrsa -out prod_private_key.pem 4096
openssl req -new -x509 -key prod_private_key.pem -out prod_cert.pem \
  -days 730 -subj "/CN=ERP-Prod/O=YourOrg"
```

## Common Pitfalls

- **Using Resource Owner Password grant in production**: Passes username/password directly, does not support MFA, and is deprecated in OAuth 2.1. Fix: `Migrate to Client Credentials or JWT Assertion for all production integrations immediately`. [src4]
- **Not monitoring certificate expiry**: JWT assertion flow fails silently when the certificate expires. Teams discover the failure only when the next integration run fails. Fix: `Automate certificate expiry monitoring; set alerts 30/14/7 days before expiry; include certificate rotation in runbooks`. [src2]
- **Wrong identity domain for app registration**: Post-IDCS migration, tenants have multiple identity domains. Registering the app in the Default domain instead of the OracleIdentityCloudService domain means tokens lack Fusion Cloud resource permissions. Fix: `Verify which domain contains the Fusion Cloud resource application (typically OracleIdentityCloudService); register confidential apps there`. [src1]
- **Ignoring LBAC when debugging auth failures**: 401/403 from LBAC looks identical to auth failures. Teams waste hours on OAuth debugging when the issue is IP allowlisting. Fix: `Check LBAC settings first; test from an allowlisted IP to isolate; add LBAC check to integration troubleshooting runbook`. [src4]
- **Not using PKCE with Authorization Code flow**: Without PKCE, authorization codes can be intercepted in man-in-the-middle attacks. Fix: `Always use PKCE (S256 method) for Authorization Code flows, even when using a confidential client`. [src5]
- **Assuming SAML federation applies to API calls**: Teams configure SAML SSO and expect it to authenticate API calls. SAML federation only applies to browser-based interactive login. Fix: `Use OAuth 2.0 grant types for all API authentication; SAML is for SSO only`. [src6, src7]

## Diagnostic Commands

```bash
# Discover all available endpoints for an identity domain
curl -s "https://<domain>.identity.oraclecloud.com/.well-known/openid-configuration" \
  | python3 -m json.tool

# Test Client Credentials token request
curl -v -X POST \
  "https://<domain>.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"

# Decode JWT access token payload (inspect claims without verification)
echo "<ACCESS_TOKEN>" | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# Look for: exp (expiry), iss (issuer), sub (subject), aud (audience), scope

# Verify token against Fusion Cloud API
curl -w "\nHTTP Status: %{http_code}\n" \
  "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# Check certificate expiry date (before it breaks your JWT flow)
openssl x509 -in cert.pem -noout -enddate
# Output: notAfter=Mar  9 00:00:00 2028 GMT

# Verify SAML metadata is accessible from identity domain
curl -s "https://<domain>.identity.oraclecloud.com/fed/v1/metadata" \
  | head -5
# Should return XML starting with <EntityDescriptor>

# Test if LBAC is blocking (compare from two different IPs)
curl -s -o /dev/null -w "%{http_code}" \
  "https://<erp-host>.fa.ocs.oraclecloud.com/fscmRestApi/resources/latest" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"
# 401 from one IP but 200 from another = LBAC blocking
```

## 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, client IDs, secrets, tokens continue to work |
| IDCS-to-IAM Region Migration | 2023-03 to 2024-06 | Complete | Automatic migration | No integration code changes required |
| Identity Domain Replication | 2024-08 | Current | None | Cross-region DR for identity domains now available |
| Fusion Cloud Release 25A | 2025-01 | Current | None auth-related | Quarterly release; API endpoints unchanged |
| Fusion Cloud Release 25B | 2025-04 | Current | None auth-related | OAuth configuration UI improvements |
| OCI IAM OAuth 2.1 Alignment | Planned 2025-2026 | Upcoming | Resource Owner Password grant likely deprecated | Migrate to Client Credentials or JWT before deprecation |

[src1, src5]

### Deprecation Policy

Oracle has not announced a formal deprecation date for Basic Authentication or Resource Owner Password grant on Fusion Cloud APIs. However, Oracle's OCI IAM best practices whitepaper strongly recommends OAuth 2.0 Client Credentials or JWT Assertion for all integrations and positions both Basic Auth and Resource Owner Password as legacy patterns. Given industry-wide movement toward OAuth 2.1 (which removes the password grant entirely), plan to migrate away from these patterns proactively. [src1, src5]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Implementing specific OAuth grant type flows for Oracle Fusion Cloud | Need to decide which auth method to use (high-level) | business/erp-integration/oracle-erp-cloud-authentication/2026 |
| Setting up SAML federation with Azure AD, Okta, or other IdP | Need Oracle NetSuite authentication (TBA/OAuth) | business/erp-integration/netsuite-tba-vs-oauth2/2026 |
| Configuring identity propagation through middleware | Need general OAuth 2.0 patterns (not Oracle-specific) | software/patterns/oauth2-client-credentials/2026 |
| Managing certificate lifecycle for JWT assertion flows | Need Salesforce OAuth authentication | business/erp-integration/salesforce-oauth-authentication/2026 |
| Setting up multi-environment auth (prod/test/dev) | Need Oracle ERP REST API capabilities (endpoints, operations) | business/erp-integration/oracle-erp-cloud-rest-api-capabilities/2026 |

## Important Caveats

- Oracle does not publish fixed API rate limits for Fusion Cloud. Throttling is adaptive per tenant and pod. The HTTP 429 response code is your only signal for rate limiting on token requests as well as API calls. [src4]
- Token lifetime is calculated as `MIN(configured_expiry, remaining_session_lifetime)`. Even if you configure a 24-hour token expiry, the session lifetime (default 8 hours) caps the effective token duration. Align both settings. [src5]
- Post-IDCS migration, tenants have at least two identity domains (Default and OracleIdentityCloudService). Some Oracle documentation still references IDCS terminology. The functionality is identical in OCI IAM identity domains. [src1]
- SAML federation only affects interactive browser login. API-level OAuth flows bypass federation entirely. Do not rely on SAML for API authentication. [src6, src7]
- Each Fusion Cloud environment has its own identity domain. OAuth registrations, certificates, tokens, and SAML federation configurations are completely separate. Test-to-prod promotion requires reconfiguring authentication in each environment. [src1]
- Oracle's OCI IAM OAuth flows best practices whitepaper recommends Client Credentials for most machine-to-machine integrations and JWT Assertion for high-security environments. Authorization Code should only be used when user-context is genuinely needed. [src5]

## Related Units
<!-- Generated from related_kos frontmatter -->

- [Oracle ERP Cloud Authentication (overview)](/business/erp-integration/oracle-erp-cloud-authentication/2026)
- [Oracle ERP Cloud REST API Capabilities](/business/erp-integration/oracle-erp-cloud-rest-api-capabilities/2026)
- [Oracle Integration Cloud Capabilities](/business/erp-integration/oracle-integration-cloud-capabilities/2026)
- [ERP Authentication Methods Comparison](/business/erp-integration/erp-authentication-comparison/2026)
- [Dynamics 365 Authentication Patterns](/business/erp-integration/dynamics-365-authentication/2026)
- [SAP Authentication Methods](/business/erp-integration/sap-authentication-methods/2026)
- [NetSuite TBA vs OAuth 2.0](/business/erp-integration/netsuite-tba-vs-oauth2/2026)
