# Source: https://gofastmcp.com/integrations/oci.md

> ## Documentation Index
> Fetch the complete documentation index at: https://gofastmcp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OCI IAM OAuth 🤝 FastMCP

> Secure your FastMCP server with OCI IAM OAuth

export const VersionBadge = ({version}) => {
  return <Badge stroke size="lg" icon="gift" iconType="regular" className="version-badge">
            New in version <code>{version}</code>
        </Badge>;
};

<VersionBadge version="2.13.0" />

This guide shows you how to secure your FastMCP server using **OCI IAM OAuth**. Since OCI IAM doesn't support Dynamic Client Registration, this integration uses the [**OIDC Proxy**](/servers/auth/oidc-proxy) pattern to bridge OCI's traditional OAuth with MCP's authentication requirements.

## Configuration

### Prerequisites

1. An OCI cloud Account with access to create an Integrated Application in an Identity Domain.
2. Your FastMCP server's URL (For dev environments, it is [http://localhost:8000](http://localhost:8000). For PROD environments, it could be [https://mcp.yourdomain.com](https://mcp.yourdomain.com))

### Step 1: Make sure client access is enabled for JWK's URL

<Steps>
  <Step title="Navigate to OCI IAM Domain Settings">
    Login to OCI console ([https://cloud.oracle.com](https://cloud.oracle.com) for OCI commercial cloud).
    From "Identity & Security" menu, open Domains page.
    On the Domains list page, select the domain that you are using for MCP Authentication.
    Open Settings tab.
    Click on "Edit Domain Settings" button.

    <Frame>
      <img src="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=189e2e2c679c33b33a79164756cb6440" alt="OCI console showing the Edit Domain Settings button in the IAM Domain settings page" data-og-width="1489" width="1489" data-og-height="307" height="307" data-path="integrations/images/oci/ocieditdomainsettingsbutton.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?w=280&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=72efbc25e978daac993b559bdc09b0d7 280w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?w=560&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=af645c2122c07997ce006428e1fb358e 560w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?w=840&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=ac35f055a4def431abc642bda1a3f08d 840w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?w=1100&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=2f22168773dbb1a0965c1ffcc700f9bd 1100w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?w=1650&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=2ec995069ee90933789fc0e381c1f985 1650w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettingsbutton.png?w=2500&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=a9a06d349b8d2fee37e8325b45a96c37 2500w" />
    </Frame>
  </Step>

  <Step title="Update Domain Setting">
    Enable "Configure client access" checkbox as shown in the screenshot.

    <Frame>
      <img src="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=3f4422ba7b3c45fec724b4bb5de6ff31" alt="OCI IAM Domain Settings" data-og-width="719" width="719" data-og-height="360" height="360" data-path="integrations/images/oci/ocieditdomainsettings.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?w=280&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=2665bbb7cc08e068a7684f2d0ddafadc 280w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?w=560&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=58d7af8b4e0b65306b443269508a2150 560w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?w=840&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=2aea4bdc7947eef4105fe42a82a349ad 840w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?w=1100&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=ded585ac89dc197f4048434c4c81fa60 1100w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?w=1650&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=465d4b3a449450d7ae38b848daab7c57 1650w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocieditdomainsettings.png?w=2500&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=d0a6358aeb13211dd1579313f4a2a26b 2500w" />
    </Frame>
  </Step>
</Steps>

### Step 2: Create OAuth client for MCP server authentication

Follow the Steps as mentioned below to create an OAuth client.

<Steps>
  <Step title="Navigate to OCI IAM Integrated Applications">
    Login to OCI console ([https://cloud.oracle.com](https://cloud.oracle.com) for OCI commercial cloud).
    From "Identity & Security" menu, open Domains page.
    On the Domains list page, select the domain in which you want to create MCP server OAuth client. If you need help finding the list page for the domain, see [Listing Identity Domains.](https://docs.oracle.com/en-us/iaas/Content/Identity/domains/to-view-identity-domains.htm#view-identity-domains).
    On the details page, select Integrated applications. A list of applications in the domain is displayed.
  </Step>

  <Step title="Add an Integrated Application">
    Select Add application.
    In the Add application window, select Confidential Application.
    Select Launch workflow.
    In the Add application details page, Enter name and description as shown below.

    <Frame>
      <img src="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=5855c5dc6cd69f8a0c53f3f103e7b4fc" alt="Adding a Confidential Integrated Application in OCI IAM Domain" data-og-width="2852" width="2852" data-og-height="1200" height="1200" data-path="integrations/images/oci/ociaddapplication.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?w=280&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=d0f4e8aa0c96a0e8aa8c1c1e08ffefe7 280w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?w=560&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=a0900eba5d20c899b2881bdabcbbdb2c 560w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?w=840&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=d8fcb00216ca7d4dc5c2294185e79957 840w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?w=1100&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=8fbc1a1ba36975fed4cbc7a106581fb9 1100w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?w=1650&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=6fd416bcf3be09d0bed64e3f2298ef06 1650w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ociaddapplication.png?w=2500&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=e6f70935717ae9907b109cd89b5057b9 2500w" />
    </Frame>
  </Step>

  <Step title="Update OAuth Configuration for an Integrated Application">
    Once the Integrated Application is created, Click on "OAuth configuration" tab.
    Click on "Edit OAuth configuration" button.
    Configure the application as OAuth client by selecting "Configure this application as a client now" radio button.
    Select "Authorization code" grant type. If you are planning to use the same OAuth client application for token exchange, select "Client credentials" grant type as well. In the sample, we will use the same client.
    For Authorization grant type, select redirect URL. In most cases, this will be the MCP server URL followed by "/oauth/callback".

    <Frame>
      <img src="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=885b0adc7c2a25ee71cf7e455b6afd62" alt="OAuth Configuration for an Integrated Application in OCI IAM Domain" data-og-width="998" width="998" data-og-height="522" height="522" data-path="integrations/images/oci/ocioauthconfiguration.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?w=280&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=ef40ce6d2ded822550d5d7938ffcd71f 280w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?w=560&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=46d8db4c87ac4966f8d15beeaeffd475 560w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?w=840&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=0eeb569886c184fd1e192fee120b06e1 840w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?w=1100&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=55bf561391a0282cd03874d884ff51f5 1100w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?w=1650&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=7308f03d616ea58d3673de12caabd045 1650w, https://mintcdn.com/fastmcp/dDafRTA33FK_2khu/integrations/images/oci/ocioauthconfiguration.png?w=2500&fit=max&auto=format&n=dDafRTA33FK_2khu&q=85&s=1244add730484e72effb5477bb3b08ee 2500w" />
    </Frame>
  </Step>

  <Step title="Activate the Integrated Application">
    Click on "Submit" button to update OAuth configuration for the client application.
    **Note: You don't need to do any special configuration to support PKCE for the OAuth client.**
    Make sure to Activate the client application.
    Note down client ID and client secret for the application. You'll use these values when configuring the OCIProvider in your code.
  </Step>
</Steps>

This is all you need to implement MCP server authentication against OCI IAM. However, you may want to use an authenticated user token to invoke OCI control plane APIs and propagate identity to the OCI control plane instead of using a service user account. In that case, you need to implement token exchange.

### Step 3: Token Exchange Setup (Only if MCP server needs to talk to OCI Control Plane)

Token exchange helps you exchange a logged-in user's OCI IAM token for an OCI control plane session token, also known as UPST (User Principal Session Token). To learn more about token exchange, refer to my [Workload Identity Federation Blog](https://www.ateam-oracle.com/post/workload-identity-federation)

For token exchange, we need to configure Identity propagation trust. The blog above discusses setting up the trust using REST APIs. However, you can also use OCI CLI. Before using the CLI command below, ensure that you have created a token exchange OAuth client. In most cases, you can use the same OAuth client that you created above. Replace `<IAM_GUID>` and `<CLIENT_ID>` in the CLI command below with your actual values.

```bash  theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
oci identity-domains identity-propagation-trust create \
--schemas '["urn:ietf:params:scim:schemas:oracle:idcs:IdentityPropagationTrust"]' \
--public-key-endpoint "https://<IAM_GUID>.identity.oraclecloud.com/admin/v1/SigningCert/jwk" \
--name "For Token Exchange" --type "JWT" \
--issuer "https://identity.oraclecloud.com/" --active true \
--endpoint "https://<IAM_GUID>.identity.oraclecloud.com" \
--subject-claim-name "sub" --allow-impersonation false \
--subject-mapping-attribute "username" \
--subject-type "User" --client-claim-name "iss" \
--client-claim-values '["https://identity.oraclecloud.com/"]' \
--oauth-clients '["<CLIENT_ID>"]'
```

To exchange access token for OCI token and create a signer object, you need to add below code in MCP server. You can then use the signer object to create any OCI control plane client.

```python  theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}

from fastmcp.server.dependencies import get_access_token
from fastmcp.utilities.logging import get_logger
from oci.auth.signers import TokenExchangeSigner
import os

logger = get_logger(__name__)

# Load configuration from environment
OCI_IAM_GUID = os.environ.get("OCI_IAM_GUID")
OCI_CLIENT_ID = os.environ.get("OCI_CLIENT_ID")
OCI_CLIENT_SECRET = os.environ.get("OCI_CLIENT_SECRET")

_global_token_cache = {} #In memory cache for OCI session token signer
    
def get_oci_signer() -> TokenExchangeSigner:

    authntoken = get_access_token()
    tokenID = authntoken.claims.get("jti")
    token = authntoken.token
    
    #Check if the signer exists for the token ID in memory cache
    cached_signer = _global_token_cache.get(tokenID)
    logger.debug(f"Global cached signer: {cached_signer}")
    if cached_signer:
        logger.debug(f"Using globally cached signer for token ID: {tokenID}")
        return cached_signer

    #If the signer is not yet created for the token then create new OCI signer object
    logger.debug(f"Creating new signer for token ID: {tokenID}")
    signer = TokenExchangeSigner(
        jwt_or_func=token,
        oci_domain_id=OCI_IAM_GUID.split(".")[0] if OCI_IAM_GUID else "",
        client_id=OCI_CLIENT_ID,
        client_secret=OCI_CLIENT_SECRET,
    )
    logger.debug(f"Signer {signer} created for token ID: {tokenID}")
        
    #Cache the signer object in memory cache
    _global_token_cache[tokenID] = signer
    logger.debug(f"Signer cached for token ID: {tokenID}")

    return signer
```

## Running MCP server

Once the setup is complete, to run the MCP server, run the below command.

```bash  theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
fastmcp run server.py:mcp --transport http --port 8000
```

To run MCP client, run the below command.

```bash  theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
python3 client.py
```

MCP Client sample is as below.

```python client.py theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client
import asyncio

async def main():
    # The client will automatically handle OCI OAuth flows
    async with Client("http://localhost:8000/mcp/", auth="oauth") as client:
        # First-time connection will open OCI login in your browser
        print("✓ Authenticated with OCI IAM")

        tools = await client.list_tools()
        print(f"🔧 Available tools ({len(tools)}):")
        for tool in tools:
            print(f"   - {tool.name}: {tool.description}")

if __name__ == "__main__":
    asyncio.run(main())
```

When you run the client for the first time:

1. Your browser will open to OCI IAM's login page
2. Sign in with your OCI account and grant the requested consent
3. After authorization, you'll be redirected back to the redirect path
4. The client receives the token and can make authenticated requests

## Production Configuration

<VersionBadge version="2.13.0" />

For production deployments with persistent token management across server restarts, configure `jwt_signing_key`, and `client_storage`:

```python server.py theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}

import os
from fastmcp import FastMCP
from fastmcp.server.auth.providers.oci import OCIProvider

from key_value.aio.stores.redis import RedisStore
from key_value.aio.wrappers.encryption import FernetEncryptionWrapper
from cryptography.fernet import Fernet

# Load configuration from environment
# Production setup with encrypted persistent token storage
auth_provider = OCIProvider(
    config_url=os.environ.get("OCI_CONFIG_URL"),
    client_id=os.environ.get("OCI_CLIENT_ID"),
    client_secret=os.environ.get("OCI_CLIENT_SECRET"),
    base_url=os.environ.get("BASE_URL", "https://your-production-domain.com"),

    # Production token management
    jwt_signing_key=os.environ["JWT_SIGNING_KEY"],
    client_storage=FernetEncryptionWrapper(
        key_value=RedisStore(
            host=os.environ["REDIS_HOST"],
            port=int(os.environ["REDIS_PORT"])
        ),
        fernet=Fernet(os.environ["STORAGE_ENCRYPTION_KEY"])
    )
)

mcp = FastMCP(name="Production OCI App", auth=auth_provider)
```

<Note>
  Parameters (`jwt_signing_key` and `client_storage`) work together to ensure tokens and client registrations survive server restarts. **Wrap your storage in `FernetEncryptionWrapper` to encrypt sensitive OAuth tokens at Rest** - without it, tokens are stored in plaintext. Store secrets in environment variables and use a persistent storage backend like Redis for distributed deployments.

  For complete details on these parameters, see the [OAuth Proxy documentation](/servers/auth/oauth-proxy#configuration-parameters).
</Note>

<Info>
  The client caches tokens locally, so you won't need to re-authenticate for subsequent runs unless the token expires or you explicitly clear the cache.
</Info>