diff --git a/en/asgardeo/docs/tutorials/agent-id-openai-authentication.md b/en/asgardeo/docs/tutorials/agent-id-openai-authentication.md new file mode 100644 index 0000000000..14477d0e95 --- /dev/null +++ b/en/asgardeo/docs/tutorials/agent-id-openai-authentication.md @@ -0,0 +1,4 @@ +{% set product_name = "Asgardeo" %} +{% set api_base_path = "https://api.asgardeo.io/t/{organization_name}" %} + +{% include "../../../includes/tutorials/agent-id-openai-authentication.md" %} diff --git a/en/asgardeo/docs/tutorials/index.md b/en/asgardeo/docs/tutorials/index.md index 7eb473f6a5..5293894717 100644 --- a/en/asgardeo/docs/tutorials/index.md +++ b/en/asgardeo/docs/tutorials/index.md @@ -14,6 +14,7 @@ See the topics listed below for end-to-end tutorials on how to use WSO2 Identity - [Integrate WSO2 Identity Platform with SMART on FHIR healthcare apps]({{base_path}}/tutorials/smart-on-fhir/) - [Secure Agentic AI Systems with WSO2 Identity Platform]({{base_path}}/tutorials/secure-agentic-ai-systems/) - [Authenticate AI Agents to the Claude API with WSO2 Agent ID]({{base_path}}/tutorials/agent-id-claude-authentication/) +- [Authenticate AI Agents to the OpenAI API with WSO2 Agent ID]({{base_path}}/tutorials/agent-id-openai-authentication/) - [Integrating WSO2 Identity Platform With WSO2 AI Gateway for Agent Identity-Aware Access Control]({{base_path}}/tutorials/wso2-ai-gateway-with-agent-identity-aware-access-control/) - [Integrating WSO2 Identity Platform With Kong AI Gateway for Agent Identity-Aware Access Control]({{base_path}}/tutorials/kong-ai-gateway-with-agent-identity-aware-access-control/) - [Secure MCP servers with WSO2 Identity Platform and integrate them with n8n agentic flows]({{base_path}}/tutorials/secure-mcp-servers-and-integrate-them-with-n8n-agentic-flows/) diff --git a/en/asgardeo/mkdocs.yml b/en/asgardeo/mkdocs.yml index 0ee778a1bb..c115cbd7a5 100644 --- a/en/asgardeo/mkdocs.yml +++ b/en/asgardeo/mkdocs.yml @@ -786,6 +786,7 @@ nav: - Secure Agentic AI Systems with WSO2 Identity Platform: tutorials/secure-agentic-ai-systems.md - Access Control for Ambient Agents: tutorials/ciba-for-ai-agents.md - Authenticate AI Agents to the Claude API with WSO2 Agent ID: tutorials/agent-id-claude-authentication.md + - Authenticate AI Agents to the OpenAI API with WSO2 Agent ID: tutorials/agent-id-openai-authentication.md - Implement End-to-End Authorization for MCP servers: tutorials/end-to-end-mcp-authorization-with-asgardeo.md - Integrating WSO2 Identity Platform With WSO2 AI Gateway for Agent Identity-Aware Access Control: tutorials/wso2-ai-gateway-with-agent-identity-aware-access-control.md - Integrating WSO2 Identity Platform With Kong AI Gateway for Agent Identity-Aware Access Control: tutorials/kong-ai-gateway-with-agent-identity-aware-access-control.md diff --git a/en/identity-server/7.2.0/docs/tutorials/agent-id-claude-authentication.md b/en/identity-server/7.2.0/docs/tutorials/agent-id-claude-authentication.md index 0272c68e82..cbf41a9ba4 100644 --- a/en/identity-server/7.2.0/docs/tutorials/agent-id-claude-authentication.md +++ b/en/identity-server/7.2.0/docs/tutorials/agent-id-claude-authentication.md @@ -1,4 +1,4 @@ {% set product_name = "WSO2 Identity Server" %} -{% set api_base_path = "https://localhost:9443" %} +{% set api_base_path = "" %} {% include "../../../../includes/tutorials/agent-id-claude-authentication.md" %} diff --git a/en/identity-server/7.2.0/docs/tutorials/agent-id-openai-authentication.md b/en/identity-server/7.2.0/docs/tutorials/agent-id-openai-authentication.md new file mode 100644 index 0000000000..1be3def6ca --- /dev/null +++ b/en/identity-server/7.2.0/docs/tutorials/agent-id-openai-authentication.md @@ -0,0 +1,4 @@ +{% set product_name = "WSO2 Identity Server" %} +{% set api_base_path = "https://localhost:9443" %} + +{% include "../../../../includes/tutorials/agent-id-openai-authentication.md" %} diff --git a/en/identity-server/7.2.0/docs/tutorials/index.md b/en/identity-server/7.2.0/docs/tutorials/index.md index 71a5f0aae7..e11d17446c 100644 --- a/en/identity-server/7.2.0/docs/tutorials/index.md +++ b/en/identity-server/7.2.0/docs/tutorials/index.md @@ -12,3 +12,4 @@ See the topics listed below for end-to-end tutorials on how to use WSO2 Identity - [Integrating WSO2 Identity Server With Kong AI Gateway for Agent Identity-Aware Access Control]({{base_path}}/tutorials/kong-ai-gateway-with-agent-identity-aware-access-control/) - [Secure MCP servers with WSO2 Identity Server and integrate them with n8n agentic flows]({{base_path}}/tutorials/secure-mcp-servers-and-integrate-them-with-n8n-agentic-flows/) - [Authenticate Agents with their own Agent ID to Claude API Using Workload Identity Federation]({{base_path}}/tutorials/agent-id-claude-authentication/) +- [Authenticate Agents with their own Agent ID to OpenAI API Using Workload Identity Federation]({{base_path}}/tutorials/agent-id-openai-authentication/) diff --git a/en/identity-server/7.2.0/mkdocs.yml b/en/identity-server/7.2.0/mkdocs.yml index a849ce60dc..78c55ab17e 100644 --- a/en/identity-server/7.2.0/mkdocs.yml +++ b/en/identity-server/7.2.0/mkdocs.yml @@ -959,6 +959,7 @@ nav: - Build your own push authenticator app: references/tutorials/build-your-own-push-authenticator-app.md - Secure Agentic AI Systems with WSO2 Identity Server: tutorials/secure-agentic-ai-systems.md - Authenticate Agents with their own Agent ID to Claude API Using Workload Identity Federation: tutorials/agent-id-claude-authentication.md + - Authenticate Agents with their own Agent ID to OpenAI API Using Workload Identity Federation: tutorials/agent-id-openai-authentication.md - Integrating WSO2 Identity Server With WSO2 AI Gateway for Agent Identity-Aware Access Control: tutorials/wso2-ai-gateway-with-agent-identity-aware-access-control.md - Integrating WSO2 Identity Server With Kong AI Gateway for Agent Identity-Aware Access Control: tutorials/kong-ai-gateway-with-agent-identity-aware-access-control.md - Secure MCP servers with WSO2 Identity Server and integrate them with n8n agentic flows: tutorials/secure-mcp-servers-and-integrate-them-with-n8n-agentic-flows.md diff --git a/en/identity-server/7.3.0/docs/tutorials/agent-id-claude-authentication.md b/en/identity-server/7.3.0/docs/tutorials/agent-id-claude-authentication.md index 0272c68e82..cbf41a9ba4 100644 --- a/en/identity-server/7.3.0/docs/tutorials/agent-id-claude-authentication.md +++ b/en/identity-server/7.3.0/docs/tutorials/agent-id-claude-authentication.md @@ -1,4 +1,4 @@ {% set product_name = "WSO2 Identity Server" %} -{% set api_base_path = "https://localhost:9443" %} +{% set api_base_path = "" %} {% include "../../../../includes/tutorials/agent-id-claude-authentication.md" %} diff --git a/en/identity-server/7.3.0/docs/tutorials/agent-id-openai-authentication.md b/en/identity-server/7.3.0/docs/tutorials/agent-id-openai-authentication.md new file mode 100644 index 0000000000..1be3def6ca --- /dev/null +++ b/en/identity-server/7.3.0/docs/tutorials/agent-id-openai-authentication.md @@ -0,0 +1,4 @@ +{% set product_name = "WSO2 Identity Server" %} +{% set api_base_path = "https://localhost:9443" %} + +{% include "../../../../includes/tutorials/agent-id-openai-authentication.md" %} diff --git a/en/identity-server/7.3.0/docs/tutorials/index.md b/en/identity-server/7.3.0/docs/tutorials/index.md index ca5d9a1317..996e9d84a6 100644 --- a/en/identity-server/7.3.0/docs/tutorials/index.md +++ b/en/identity-server/7.3.0/docs/tutorials/index.md @@ -13,3 +13,4 @@ See the topics listed below for end-to-end tutorials on how to use WSO2 Identity - [Integrating WSO2 Identity Server With Kong AI Gateway for Agent Identity-Aware Access Control]({{base_path}}/tutorials/kong-ai-gateway-with-agent-identity-aware-access-control/) - [Secure MCP servers with WSO2 Identity Server and integrate them with n8n agentic flows]({{base_path}}/tutorials/secure-mcp-servers-and-integrate-them-with-n8n-agentic-flows/) - [Authenticate Agents with their own Agent ID to Claude API Using Workload Identity Federation]({{base_path}}/tutorials/agent-id-claude-authentication/) +- [Authenticate Agents with their own Agent ID to OpenAI API Using Workload Identity Federation]({{base_path}}/tutorials/agent-id-openai-authentication/) diff --git a/en/identity-server/7.3.0/mkdocs.yml b/en/identity-server/7.3.0/mkdocs.yml index 9bd6bf72ce..f4cb9627e2 100644 --- a/en/identity-server/7.3.0/mkdocs.yml +++ b/en/identity-server/7.3.0/mkdocs.yml @@ -1001,6 +1001,7 @@ nav: - Secure Agentic AI Systems with WSO2 Identity Server: tutorials/secure-agentic-ai-systems.md - Access Control for Ambient Agents: tutorials/ciba-for-ai-agents.md - Authenticate AI Agents to the Claude API with WSO2 Agent ID: tutorials/agent-id-claude-authentication.md + - Authenticate AI Agents to the OpenAI API with WSO2 Agent ID: tutorials/agent-id-openai-authentication.md - Setup: - Install: - Install: deploy/get-started/install.md diff --git a/en/identity-server/next/docs/tutorials/agent-id-claude-authentication.md b/en/identity-server/next/docs/tutorials/agent-id-claude-authentication.md index 0272c68e82..cbf41a9ba4 100644 --- a/en/identity-server/next/docs/tutorials/agent-id-claude-authentication.md +++ b/en/identity-server/next/docs/tutorials/agent-id-claude-authentication.md @@ -1,4 +1,4 @@ {% set product_name = "WSO2 Identity Server" %} -{% set api_base_path = "https://localhost:9443" %} +{% set api_base_path = "" %} {% include "../../../../includes/tutorials/agent-id-claude-authentication.md" %} diff --git a/en/identity-server/next/docs/tutorials/agent-id-openai-authentication.md b/en/identity-server/next/docs/tutorials/agent-id-openai-authentication.md new file mode 100644 index 0000000000..1be3def6ca --- /dev/null +++ b/en/identity-server/next/docs/tutorials/agent-id-openai-authentication.md @@ -0,0 +1,4 @@ +{% set product_name = "WSO2 Identity Server" %} +{% set api_base_path = "https://localhost:9443" %} + +{% include "../../../../includes/tutorials/agent-id-openai-authentication.md" %} diff --git a/en/identity-server/next/docs/tutorials/index.md b/en/identity-server/next/docs/tutorials/index.md index 20016cdead..74a73cc964 100644 --- a/en/identity-server/next/docs/tutorials/index.md +++ b/en/identity-server/next/docs/tutorials/index.md @@ -13,3 +13,4 @@ See the topics listed below for end-to-end tutorials on how to use WSO2 Identity - [Integrating WSO2 Identity Server With Kong AI Gateway for Agent Identity-Aware Access Control]({{base_path}}/tutorials/kong-ai-gateway-with-agent-identity-aware-access-control/) - [Secure MCP servers with WSO2 Identity Server and integrate them with n8n agentic flows]({{base_path}}/tutorials/secure-mcp-servers-and-integrate-them-with-n8n-agentic-flows/) - [Authenticate Agents with their own Agent ID to Claude API Using Workload Identity Federation]({{base_path}}/tutorials/agent-id-claude-authentication/) +- [Authenticate Agents with their own Agent ID to OpenAI API Using Workload Identity Federation]({{base_path}}/tutorials/agent-id-openai-authentication/) diff --git a/en/identity-server/next/mkdocs.yml b/en/identity-server/next/mkdocs.yml index 13804903ca..68a5eccd36 100644 --- a/en/identity-server/next/mkdocs.yml +++ b/en/identity-server/next/mkdocs.yml @@ -1016,6 +1016,7 @@ nav: - Integrating WSO2 Identity Server With Kong AI Gateway for Agent Identity-Aware Access Control: tutorials/kong-ai-gateway-with-agent-identity-aware-access-control.md - Secure MCP servers with WSO2 Identity Server and integrate them with n8n agentic flows: tutorials/secure-mcp-servers-and-integrate-them-with-n8n-agentic-flows.md - Authenticate AI Agents to the Claude API with WSO2 Agent ID: tutorials/agent-id-claude-authentication.md + - Authenticate AI Agents to the OpenAI API with WSO2 Agent ID: tutorials/agent-id-openai-authentication.md - Setup: - Install: diff --git a/en/includes/tutorials/agent-id-claude-authentication.md b/en/includes/tutorials/agent-id-claude-authentication.md index 70e356e3e7..ca96c2be39 100644 --- a/en/includes/tutorials/agent-id-claude-authentication.md +++ b/en/includes/tutorials/agent-id-claude-authentication.md @@ -17,9 +17,17 @@ The authentication flow works as follows: Before you begin, ensure you have the following: - An [Anthropic](https://console.anthropic.com/) account with access to the Claude Console. +{% if product_name == "WSO2 Identity Server" %} +- A deployed instance of {{product_name}} that is accessible via a public URL `{{api_base_path}}`. +{% endif %} - `curl` and `jq` installed on your machine (for the shell-based approach). - Python 3.9+ (for the SDK-based approach). +{% if product_name == "WSO2 Identity Server" %} +!!! note + To configure Anthropic to work with {{product_name}}, your {{product_name}} instance must be publicly accessible over HTTPS and serve traffic on port 443. Anthropic retrieves the JWKS endpoint only from a publicly accessible HTTPS endpoint. +{% endif %} + ## Step 1: Register an Agent in {{product_name}} This is what replaces the shared static API key. Each agent gets its own Agent ID and Secret, so it's a distinct principal your security model can reason about, not just a possessor of a key. @@ -159,9 +167,10 @@ from asgardeo_ai import AgentAuthManager, AgentConfig from anthropic import Anthropic, WorkloadIdentityCredentials # {{product_name}} configuration -config = AgentIDConfig( +config = AsgardeoConfig( base_url="{{ api_base_path }}", client_id="", + client_secret="", redirect_uri="", ) @@ -181,8 +190,8 @@ class AgentIDTokenProvider: EXPIRY_BUFFER_SECONDS = 60 - def __init__(self, {{product_name}}_config, agent_cfg, scopes=None): - self.{{product_name}}_config = {{product_name}}_config + def __init__(self, identity_provider_config, agent_cfg, scopes=None): + self.identity_provider_config = identity_provider_config self.agent_cfg = agent_cfg self.scopes = scopes or ["openid", "profile"] self._cached_token = None @@ -202,7 +211,7 @@ class AgentIDTokenProvider: async def _refresh_token(self): async with AgentAuthManager( - self.{{product_name}}_config, self.agent_cfg + self.identity_provider_config, self.agent_cfg ) as auth_manager: agent_token = await auth_manager.get_agent_token( self.scopes @@ -235,7 +244,7 @@ message = client.messages.create( print(message.content[0].text) ``` -The `AsgardeoTokenProvider` handles token caching and refresh with a 60-second buffer before expiry. The Anthropic SDK's `WorkloadIdentityCredentials` manages the Claude access token lifecycle independently, calling the provider whenever it needs a fresh identity token for the WIF exchange. Together, they allow long-running agents to operate continuously without manual token management. +The `AgentIDTokenProvider` handles token caching and refresh with a 60-second buffer before expiry. The Anthropic SDK's `WorkloadIdentityCredentials` manages the Claude access token lifecycle independently, calling the provider whenever it needs a fresh identity token for the WIF exchange. Together, they allow long-running agents to operate continuously without manual token management. ## What's Next diff --git a/en/includes/tutorials/agent-id-openai-authentication.md b/en/includes/tutorials/agent-id-openai-authentication.md new file mode 100644 index 0000000000..77ec96f011 --- /dev/null +++ b/en/includes/tutorials/agent-id-openai-authentication.md @@ -0,0 +1,234 @@ +# Authenticate Agents with their own Agent ID to OpenAI API Using Workload Identity Federation + +This tutorial walks you through connecting an AI agent registered in {{product_name}} to the OpenAI API using [OpenAI's Workload Identity Federation (WIF)](https://developers.openai.com/api/docs/guides/workload-identity-federation). By the end of this tutorial, your agent will authenticate with {{product_name}}, obtain a signed JWT, exchange it for a short-lived OpenAI access token, and make API calls without any static API keys. + +## Overview + +The authentication flow works as follows: + +1. Your AI agent authenticates with {{product_name}} using its Agent ID and Secret. +2. {{product_name}} issues a signed JWT (access token) to the agent. +3. The agent presents this JWT to OpenAI's token endpoint. +4. OpenAI validates the JWT and returns a short-lived access token. +5. The agent uses the access token to call the OpenAI API. + +## Prerequisites + +Before you begin, ensure you have the following: + +- An [OpenAI Developer](https://developers.openai.com/) account with access to the [API Platform](https://platform.openai.com/login). +- `curl` and `jq` installed on your machine (for the shell-based approach). +- Python 3.9+ (for the SDK-based approach). + +## Step 1: Register an Agent in {{product_name}} + +This is what replaces the shared static API key. Each agent gets its own Agent ID and Secret, so it's a distinct principal your security model can reason about, not just a possessor of a key. + +1. Log in to the {{product_name}} Console. +2. Navigate to **Agents** tab. +3. Click **New Agent** and provide a descriptive name for your agent. +4. Assign the agent to appropriate groups and roles based on the resources it needs to access. +5. Note down the **Agent ID** and **Agent Secret** that {{product_name}} generates. + +## Step 2: Create an Application in {{product_name}} + +Your agent needs an OAuth application to obtain tokens through the app-native authentication flow. + +The application is the channel the agent authenticates through. It's what issues the JWT that OpenAI will later validate, so its protocol settings (grant type, token type, audience) need to line up with what OpenAI's identity provider settings expects. + +1. Go to **Applications**, click **New Application** and select **Standard-Based Application**. +2. Give a suitable name and tick the box with **Allow AI agents to sign into this application**. +3. In the **Protocol** tab, configure the following: + - Enable the **Authorization Code** grant type. + - Make sure Access token type is **JWT**. + - Set an authorized redirect URI (e.g., `https://example.com/callback`). +4. From the **Advanced** tab, enable **App Native Authentication**. +5. Click **Save** and note down the **Client ID** and **Client Secret**. + +## Step 3: Configure {{product_name}} as a Workload Identity Provider in OpenAI Platform + +From this point on, OpenAI will accept identity assertions signed by {{product_name}}. Registering the issuer and JWKS URL is what lets OpenAI verify the JWT's signature without you managing any shared secret between the two systems. + +1. In the OpenAI Platform, go to **Security > Workload Identity Provider**. +2. Click on **Create Identity Provider** and configure the following. + - **OIDC Issuer URL**: `{{ api_base_path }}/oauth2/token` + - **Audience**: `` + {% if product_name == "WSO2 Identity Server" %} + - If you are running a local instance of {{product_name}}, check **Use uploaded JWKS for token verification** and paste your JWKS JSON in the textbox. + {% endif %} +3. Click **create** and note down the **Provider ID** (format: `idp_...`). + +{% if product_name == "WSO2 Identity Server" %} +!!! note + To get the JWKS JSON from your local {{product_name}} instance, you can fetch the `{{api_base_path}}/oauth2/jwks` endpoint. When enabled, OpenAI verifies tokens against this uploaded JWKS instead of fetching keys from OIDC discovery. +{% endif %} + +## Step 4: Set Up the Service Account Mapping in OpenAI Platform + +The service account is the identity the agent acts as on the OpenAI side. A service account mapping defines which external identities can mint access tokens for an OpenAI service account. This mapping enables OpenAI to bind JWT's issuer and subject claims to a specific service account. + +1. In the OpenAI Platform, go to **Security** and click on the workload identity provider you just created. +2. Click on **Create mapping**. + - Set Name to be a unique value within the Workload Identity Provider. + - Set the **Agent ID** (from {{product_name}}) as the `sub` claim value. + - If needed, you can add more claims to validate such as `act`. OpenAI makes sure all the cliams are matching before issuing a new token. + - Set **Project** to the OpenAI project that owns the target service account. + - Give a name to the service account. Check the box to create a new account. + - Select appropriate permissions to further narrow access tokens minted from this mapping. +3. Click **create**. +4. Note down the **service account ID** (format: `user-..`). You can get the service account id either from hovering over the 'i' symbol or going to the **People** tab. + +## Step 5: Authenticate Your Agent + +With all the configuration in place, your agent can now authenticate and call the OpenAI API. + +### Option A: Shell Script + +This approach demonstrates the full flow using `curl` commands. + +#### Phase 1: Obtain an Identity Token from {{product_name}} + +The agent authenticates with {{product_name}} using the app-native authentication API. This is a redirect-free, API-driven flow that uses PKCE (RFC 7636) for security. The flow involves three API calls: + +1. Initiate an authorize request with `response_mode=direct` and PKCE parameters. +2. Authenticate with the Agent ID and Secret via the `/authn` endpoint. +3. Exchange the resulting authorization code for a JWT access token. + +For the complete walkthrough of this flow, see the [{{product_name}} documentation on AI agent authentication]({{base_path}}/guides/agentic-ai/ai-agents/agent-authentication/#ai-agent-acting-on-its-own/). + +The resulting `access_token` from {{product_name}} is a signed JWT that you will present to OpenAI's WIF. + +#### Phase 2: Exchange the JWT for a OpenAI Access Token + +Present the {{product_name}}-issued JWT to OpenAI's token endpoint: + +```bash +OPENAI_RESPONSE=$(curl -s https://auth.openai.com/oauth/token \ + -H 'content-type: application/json' \ + --data '{ + "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", + "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", + "subject_token": "'$JWT'", + "identity_provider_id": "idp_...", + "service_account_id": "user-..." + }') + +ACCESS_TOKEN=$(echo "$OPENAI_RESPONSE" | jq -r .access_token) +``` + +#### Phase 3: Call the OpenAI API + +Use the short-lived access token to make API calls: + +```bash +curl -s https://api.openai.com/v1/responses \ + -H "authorization: Bearer $ACCESS_TOKEN" \ + -H 'content-type: application/json' \ + --data '{ + "model": "gpt-5.4-mini", + "input": "write a 3 word sentence", + "store": true + }' +``` + +### Option B: Python SDK + +For production agents, use the OpenAI Python SDK with the {{product_name}} Python SDK for automatic token management. + +#### Install dependencies + +```bash +pip install openai asgardeo asgardeo-ai +``` + +#### Complete example + +```python +import asyncio +import time +from asgardeo import AsgardeoConfig +from asgardeo_ai import AgentAuthManager, AgentConfig +from openai import OpenAI +from openai.auth import SubjectTokenProvider + +# {{product_name}} configuration +config = AsgardeoConfig( + base_url="{{ api_base_path }}", + client_id="", + client_secret="", + redirect_uri="", +) + +# Agent credentials +agent_config = AgentConfig( + agent_id="", + agent_secret="", +) + +def token_provider( + identity_provider_config: AsgardeoConfig, + agent_cfg: AgentConfig, + scopes=["openid", "profile"] + ) -> SubjectTokenProvider: + """ + Provide JWT access token from {{product_name}} to OpenAI WIF. + + It caches the token and refreshes automatically when expired. + The OpenAI SDK calls this function whenever it needs a + new token for the WIF exchange. + """ + + EXPIRY_BUFFER_SECONDS = 60 + cached_token = None + token_expiry : float = 0 + + def is_token_valid(): + if cached_token is None: + return False + return time.time() < ( + token_expiry - EXPIRY_BUFFER_SECONDS + ) + + async def refresh_token(): + nonlocal cached_token, token_expiry + async with AgentAuthManager( + identity_provider_config, agent_cfg + ) as auth_manager: + agent_token = await auth_manager.get_agent_token(scopes) + cached_token = agent_token.access_token + token_expiry = ( + time.time() + agent_token.expires_in + ) + return cached_token + + def get_token() -> str: + if is_token_valid(): + return cached_token + return asyncio.run(refresh_token()) + + return {"token_type": "jwt", "get_token": get_token} + +# Initialize the OpenAI client +client = OpenAI( + workload_identity={ + "identity_provider_id": "idp_...", + "service_account_id": "user-...", + "provider": token_provider(config, agent_config) + }, +) + +# Make an API call +response = client.responses.create( + model="gpt-5.4-mini", + input="Write a 3 word sentence" +) + +print(response.output_text) +``` + +The `token_provider()` function handles token caching and refresh with a 60-second buffer before expiry. The OpenAI SDK manages the OpenAI access token lifecycle independently, calling the provider whenever it needs a fresh identity token for the WIF exchange. Together, they allow long-running agents to operate continuously without manual token management. + +## What's Next + +- Learn more about [{{product_name}} Agent ID]({{base_path}}/guides/agentic-ai/ai-agents/). +- Secure agents access to [MCP Servers]({{base_path}}/guides/agentic-ai/mcp/)