OpenAI Plugin Authentication Policies: ON_INSTALL vs ON_USE

OpenAI plugins implement either an ON_INSTALL policy that persists OAuth refresh tokens across user sessions or an ON_USE policy that requires fresh authorization for every API call, with the behavior controlled by the auth.policy field in the .codex-plugin/plugin.json manifest.

The openai/plugins repository defines how ChatGPT extensions manage user consent and secure data access. These two authentication policies determine exactly when the OAuth flow executes and how long resulting tokens remain valid, directly impacting both security posture and user experience.

Understanding ON_INSTALL vs ON_USE Authentication Policies

OpenAI plugins access user data through OAuth 2.0 flows, but the timing of token acquisition and storage duration depends on the configured authentication policy declared in the plugin manifest.

ON_INSTALL: Persistent Cross-Session Access

The ON_INSTALL policy triggers the OAuth authorization flow once when the user first adds the plugin to ChatGPT. After the user grants permission, the platform stores the resulting refresh token in encrypted storage and automatically manages token rotation for all subsequent API calls.

  • Token lifecycle: Acquired at installation, persisted indefinitely, refreshed automatically by the platform
  • User experience: Single consent dialog during setup; seamless operation thereafter
  • Best for: Long-lived integrations like calendar synchronization, document repositories, or CRM connections

ON_USE: Ephemeral Request-Scoped Authorization

The ON_USE policy initiates the OAuth flow (or accepts a short-lived token) each time the user invokes the plugin. The platform discards the token immediately after the request completes, ensuring no persistent access exists between interactions.

  • Token lifecycle: Acquired per request, used once, then discarded
  • User experience: Just-in-time consent dialogs or manual token entry for sensitive operations
  • Best for: High-security contexts like banking widgets, medical data access, or any scenario requiring explicit permission per action

How to Declare Authentication Policies in the Plugin Manifest

The authentication policy is declared in the plugin manifest located at plugins/<plugin-name>/.codex-plugin/plugin.json within the repository. The auth object contains the policy field that accepts either "oninstall" or "onuse" as its value.

ON_INSTALL Configuration Example

{
  "schema_version": "v1",
  "name_for_human": "My Calendar",
  "name_for_model": "my_calendar",
  "description_for_human": "Read and write your Google Calendar events.",
  "description_for_model": "Provides calendar CRUD operations.",
  "auth": {
    "type": "oauth",
    "policy": "oninstall",
    "authorization_url": "https://accounts.google.com/o/oauth2/auth",
    "client_id": "YOUR_GOOGLE_CLIENT_ID",
    "scope": "https://www.googleapis.com/auth/calendar",
    "redirect_uri": "https://my-plugin.example.com/oauth/callback"
  },
  "api": {
    "type": "openapi",
    "url": "https://my-plugin.example.com/openapi.yaml"
  }
}

When ChatGPT processes this manifest, it executes the OAuth flow immediately upon plugin installation and stores the refresh token in the platform's secure credential store. Subsequent API calls automatically include valid access tokens without additional user interaction.

ON_USE Configuration Example

{
  "schema_version": "v1",
  "name_for_human": "Secure Banking",
  "name_for_model": "secure_banking",
  "description_for_human": "View account balances and transactions.",
  "description_for_model": "Provides banking data on demand.",
  "auth": {
    "type": "oauth",
    "policy": "onuse",
    "authorization_url": "https://bank.example.com/oauth/authorize",
    "client_id": "BANK_CLIENT_ID",
    "scope": "accounts.read transactions.read",
    "redirect_uri": "https://my-plugin.example.com/oauth/callback"
  },
  "api": {
    "type": "openapi",
    "url": "https://my-plugin.example.com/openapi.yaml"
  }
}

With this configuration, ChatGPT requests authorization each time the user queries the plugin. The token exists only for the duration of the specific API call, after which the platform purges it from memory.

Implementing Server-Side Token Handling

Your plugin backend must handle token retrieval differently depending on the active policy. The OpenAI platform communicates the current policy through request metadata, allowing your server to retrieve tokens from the appropriate source.

async function getAccessToken(req) {
  const policy = req.pluginAuthPolicy; // "oninstall" | "onuse"
  
  if (policy === "oninstall") {
    // Token is cached by OpenAI; retrieve from platform storage
    return await openai.getStoredToken(req.pluginId);
  } else {
    // ONUSE – token arrives in request headers from fresh OAuth flow
    const bearer = req.headers.authorization || "";
    return bearer.replace(/^Bearer\s+/i, "");
  }
}

In the openai/plugins repository, reference implementations in plugins/**/oauth/SKILL.md demonstrate production-ready patterns for both token management strategies.

Key Source Files in the openai/plugins Repository

The following files contain authoritative definitions and examples for authentication policy implementation:

  • README.md – Overview of the plugin architecture and security model
  • plugins/**/SKILL.md – Individual plugin definitions including authentication requirements
  • plugins/**/references/authentication.md – Detailed OAuth flow documentation for specific providers (e.g., Zoom, Google)
  • plugins/**/oauth/SKILL.md – Concrete implementation examples for both ON_INSTALL and ON_USE flows
  • plugins/<plugin-name>/.codex-plugin/plugin.json – The actual manifest files where auth.policy is defined

Each plugin's manifest in .codex-plugin/plugin.json serves as the single source of truth for which authentication policy applies to that specific integration.

Summary

  • ON_INSTALL persists OAuth tokens across sessions, fetching them once during plugin installation and automatically refreshing them for subsequent calls
  • ON_USE treats tokens as ephemeral, requiring fresh authorization for every request and discarding tokens immediately after use
  • Configure the policy via the auth.policy field in .codex-plugin/plugin.json using values "oninstall" or "onuse"
  • ON_INSTALL suits long-lived integrations requiring seamless user experience; ON_USE provides maximum security for sensitive, infrequent operations
  • Reference implementations are available in the plugins/**/oauth/SKILL.md and plugins/**/references/authentication.md files within the openai/plugins repository

Frequently Asked Questions

What happens if I don't specify an authentication policy in my plugin manifest?

If you omit the auth.policy field, the OpenAI platform defaults to behavior based on the auth.type field. However, explicit declaration is recommended because the default behavior may vary by schema version. Always define auth.policy as either "oninstall" or "onuse" to ensure predictable token management.

Can I switch from ON_INSTALL to ON_USE after users have already installed my plugin?

Changing the authentication policy after deployment requires users to re-authenticate. If you switch from ON_INSTALL to ON_USE, existing installations lose their persisted tokens and users must authorize each subsequent request. Plan this migration carefully to avoid disrupting active user sessions.

Does ON_USE support automatic token refresh like ON_INSTALL?

No. The ON_USE policy intentionally does not support automatic refresh because tokens are discarded immediately after the request completes. Each invocation requires a complete OAuth flow or fresh token provision. This design ensures that no long-lived credentials exist in the system, which is the primary security benefit of the ON_USE model.

Where does OpenAI store ON_INSTALL tokens?

According to the openai/plugins repository structure, ON_INSTALL tokens are stored in OpenAI's encrypted plugin data store, not on your servers. Your plugin receives only temporary access tokens via API calls, while refresh tokens remain secured by the platform's infrastructure. This architecture is documented in plugins/**/references/authentication.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →