Skip to content

Token Factory

Location: inception_core/libs/src/auth/token_factory/
Package: part of inception_core/libs — installed as a local editable package

TokenFactory is the central credential translation library for the platform. It converts an incoming caller credential (an IDCS access token, OCI signer dict, or OCI CLI profile name) into exactly the credential format a downstream target needs — Oracle DB scoped token, OCI SDK signer, or OAuth access token — so every consumer gets a consistent, tested entry point without implementing JWT assertion signing, UPST handling, Vault secret retrieval, or token exchange individually.


Why it exists

Different downstream targets in this platform consume different credential types:

Target Required credential
Oracle Autonomous Database Scoped DB token + session private key
OCI SDK clients (Object Storage, etc.) TokenExchangeSigner backed by a UPST
Downstream OAuth APIs Regular OAuth Bearer token
Identity resolution user_id extracted from a token claim

Without TokenFactory, every client would duplicate the same JWT assertion construction, Identity Propagation Trust setup, Vault secret reads, and OCI signer wiring. TokenFactory centralises that logic once, behind a two-call API.


Quick start

from token_factory import TokenFactory

factory = TokenFactory.from_env()
result = factory.get_token(caller_access_token, "oracle-database", scope="urn:oracle:db::id::*")

db_token = result["token"]
session_private_key_pem = result["private_key_pem"]

API

TokenFactory.from_env()

Loads all configuration from environment variables once. Returns a configured TokenFactory instance ready for get_token() calls.

factory.get_token(credential, target_tool, scope=None)

Performs the credential translation.

Parameter Required Description
credential yes Caller credential — access token string, OCI signer dict, or OCI CLI profile name
target_tool yes Requested output type: oracle-database, oci-service, oauth, or userid
scope conditional Required for oracle-database. Optional for oauth and userid. Not used for oci-service.

Supported flows

oracle-database

Exchanges a caller access token for a scoped Oracle Database token plus the matching session private key material. Used by MCP ADW server and any agent that opens a DB connection under the end user's identity.

result = factory.get_token(caller_token, "oracle-database", scope="urn:oracle:db::id::*")
# result["token"]           → DB access token
# result["private_key_pem"] → session private key (PEM)
# result["expires_in"]      → seconds until expiry

Dependencies: JWT assertion signing, IdentityPropagationTrust, TokenExchangeSigner, OCI Identity Data Plane generate_scoped_access_token.


oci-service

Returns an OCI TokenExchangeSigner backed by a UPST. Pass it directly to any OCI SDK client as signer=. Used by mcp_os (ociclients.py) to sign Object Storage API calls on behalf of the authenticated user.

from oci.object_storage import ObjectStorageClient

signer = factory.get_token(caller_token, "oci-service")
client = ObjectStorageClient(config={"region": "us-chicago-1"}, signer=signer)

Dependencies: JWT assertion signing, IdentityPropagationTrust, TokenExchangeSigner.


oauth

Exchanges a caller credential for a regular OAuth access token from the Identity Domain. Accepts three credential shapes:

# From an access token string (JWT assertion flow)
result = factory.get_token(caller_token, "oauth", scope="urn:opc:idm:__myscopes__")

# From an OCI signer dict
signer_dict = {"tenancy": "...", "user": "...", "fingerprint": "...",
               "region": "...", "private_key_content": "<pem>"}
result = factory.get_token(signer_dict, "oauth")

# From an OCI CLI profile name
result = factory.get_token("DEFAULT", "oauth")

# result["token"]      → OAuth access token
# result["token_type"] → "Bearer"
# result["expires_in"] → seconds until expiry

userid

Resolves the user_id for the caller without handing the full access token to the consumer. Useful for audit logging and session attribution.

result = factory.get_token(caller_token, "userid")
# result["user_id"] → resolved subject identifier

Accepted credential shapes

Shape Supported flows Notes
Access token string all flows Required for oracle-database and oci-service
OCI signer dict oauth, userid Needs tenancy, user, fingerprint, region, and one of private_key_file/private_key_content
OCI CLI profile name oauth, userid Resolved from ~/.oci/config

Return types

target_tool Return type Fields
oracle-database dict token, private_key_pem, expires_in, token_type, issued_token_type
oci-service TokenExchangeSigner OCI SDK signer object — not a dict
oauth dict token, expires_in, token_type, issued_token_type
userid dict user_id, issued_token_type

Configuration

TokenFactory.from_env() reads the following environment variables:

Required

Variable Purpose
DOMAIN_URL Identity Domain base URL — https://<domain>.identity.oraclecloud.com:443
DOMAIN_OCI_REGION OCI region for TokenExchangeSigner and Identity Data Plane calls
TOKEN_EXCHANGE_CREDS_OCID OCI Vault secret OCID containing client_id:client_secret for the token-factory confidential app
TOKEN_FACTORY_ISSUER JWT iss claim used when building assertions — must match the configured IdentityPropagationTrust issuer
TOKEN_FACTORY_PRIVATE_KEY_PEM or TOKEN_FACTORY_PRIVATE_KEY_SECRET_OCID or TOKEN_FACTORY_PRIVATE_KEY_PATH RSA private key for JWT assertion signing (one source required)
TOKEN_FACTORY_CERT_PEM or TOKEN_FACTORY_CERT_SECRET_OCID or TOKEN_FACTORY_CERT_PATH X.509 certificate matching the private key (one source required)

Optional

Variable Default Purpose
TOKEN_FACTORY_KID SIGNING_KEY JWT kid header for oauth/userid assertions — set to the Identity Domain certificate store alias
TOKEN_FACTORY_PRIVATE_KEY_PASSPHRASE Passphrase for encrypted private keys
TOKEN_FACTORY_OCI_REGION derived from OCID Region override for Vault secret reads
TOKEN_FACTORY_OCI_AUTH_MODE instance-principal OCI auth mode: instance-principal or oci-profile
TOKEN_FACTORY_OCI_AUTH_PROFILE DEFAULT OCI CLI profile when oci-profile mode is set
TOKEN_FACTORY_PROPAGATION_TRUST_CLAIM Additional JWT claim injected for oracle-database and oci-service — format claim_name:claim_value
TOKEN_FACTORY_UPST_PUBLIC_KEY_FORMAT single-line Ephemeral public key format during UPST exchange: single-line or pem
TOKEN_EXCHANGE_TIMEOUT_SECONDS 30 HTTP timeout for upstream token exchange calls
TOKEN_FACTORY_LOG_FULL_ASSERTION Log full compact JWT (debug only — assertions are replay-sensitive)

Minimal environment example

DOMAIN_URL="https://<domain>.identity.oraclecloud.com:443"
DOMAIN_OCI_REGION="us-chicago-1"
TOKEN_EXCHANGE_CREDS_OCID="ocid1.vaultsecret.oc1..<app-secret>"
TOKEN_FACTORY_ISSUER="https://upst.tokenfactory/"
TOKEN_FACTORY_PRIVATE_KEY_SECRET_OCID="ocid1.vaultsecret.oc1..<private-key>"
TOKEN_FACTORY_CERT_SECRET_OCID="ocid1.vaultsecret.oc1..<certificate>"
TOKEN_FACTORY_KID="token-factory-cert"
TOKEN_FACTORY_PROPAGATION_TRUST_CLAIM="upstclient:tokenexchange"

OCI signer fallback order

Factory-owned OCI SDK clients (for Vault reads, Identity Data Plane calls) resolve credentials in this order:

  1. Resource Principals — automatic inside OCI Functions or Container Instances
  2. Instance Principals — attempted with a 5-second timeout; skipped automatically when the metadata endpoint (169.254.169.254) is unreachable
  3. API Key (~/.oci/config) — falls back to the DEFAULT profile on developer laptops

No extra configuration is needed for local development as long as ~/.oci/config is present and valid.


OCI prerequisites

1. Confidential OAuth app (token-factory client)

Create a confidential app in the Identity Domain used by DOMAIN_URL:

  • Enable client_credentials
  • Enable jwt-assertion
  • Store client_id:client_secret in the Vault secret referenced by TOKEN_EXCHANGE_CREDS_OCID

2. IdentityPropagationTrust (for oracle-database and oci-service)

curl -X POST \
  -H 'Authorization: Bearer <admin-token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "active": true,
    "allowImpersonation": false,
    "issuer": "https://upst.tokenfactory/",
    "name": "Token Trust JWT to UPST",
    "oauthClients": ["<token-factory-client-id>"],
    "publicCertificate": "<base64-encoded-leaf-cert>",
    "subjectClaimName": "sub",
    "subjectMappingAttribute": "userName",
    "subjectType": "User",
    "type": "JWT",
    "clientClaimName": "upstclient",
    "clientClaimValues": ["tokenexchange"],
    "schemas": ["urn:ietf:params:scim:schemas:oracle:idcs:IdentityPropagationTrust"]
  }' \
  'https://<domain>.identity.oraclecloud.com:443/admin/v1/IdentityPropagationTrusts'

3. Identity Domain certificate store (TOKEN_FACTORY_KID)

For oauth and userid flows: - Load the token-factory public key certificate into the Identity Domain certificate store - Set the certificate alias to match TOKEN_FACTORY_KID - Configure the same certificate locally via TOKEN_FACTORY_CERT_* - Configure the matching private key via TOKEN_FACTORY_PRIVATE_KEY_*


OCI Vault secret format

Secret Contents
TOKEN_EXCHANGE_CREDS_OCID Plain text: client_id:client_secret
TOKEN_FACTORY_PRIVATE_KEY_SECRET_OCID PEM-encoded RSA private key
TOKEN_FACTORY_CERT_SECRET_OCID PEM-encoded X.509 certificate

The runtime principal must have IAM read permission on every referenced secret.


Error types

Exception Cause
ValueError Unsupported target_tool, missing scope for oracle-database, or non-token credential passed to oracle-database/oci-service
ConfigurationError Missing or invalid environment variable at config-load time
TokenExchangeError Upstream token exchange or JWT decode failure

Where it is used

Consumer Flow File
MCP SQLcl server (mcp_sqlcl) DB token for caller identity propagation src/auth/ociclients.pyget_db_token()
MCP Object Storage server (mcp_os) OCI signer for Object Storage calls src/auth/ociclients.pyget_oci_signer()
E2E ADB pattern DB token for VPD row-level security user_e2e_token_exchange_adb backend
E2E Object Storage pattern OCI signer for Object Storage operations user_e2e_token_exchange_os backend

  • Solution Patternsuser_e2e_token_exchange_adb and user_e2e_token_exchange_os show full end-to-end usage
  • MCP SQLcl Server — uses get_db_token() from ociclients.py
  • MCP Object Storage Server — uses get_oci_signer() from ociclients.py
  • inception_core/libs/src/auth/token_factory/_factory_support.py — internal implementation (JWT assertion building, UPST exchange, Vault client)