# Authentication Requirements for Plugins in the OpenAI Repository: Manifest and Skill Implementation

> Understand OpenAI plugin authentication requirements. Learn how to declare auth in manifests and implement flows in skill files for secure API access.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-24

---

**Plugins in the openai/plugins repository must declare their authentication scheme in the manifest’s `authentication` field and implement the corresponding flow in skill files to securely access third-party APIs.**

The openai/plugins repository provides a framework for extending OpenAI’s platform through external service integrations. Because these plugins invoke third-party APIs, satisfying the authentication requirements for plugins is mandatory before any skill code executes. Each plugin must define its auth model at both the manifest level and the skill implementation level according to the target service’s specifications.

## Manifest-Level Authentication Declaration

Every plugin’s root directory contains a `*.codex-plugin/plugin.json` manifest file that defines the plugin’s structure and requirements. The manifest includes an `authentication` field that declares which auth scheme the plugin expects, such as `api_key`, `oauth2`, or `jwt`.

This declaration allows the OpenAI runtime to enforce the correct authentication flow before executing any skill code. If the request lacks the credentials specified in the manifest, the platform rejects the call with a 401 error. The generic manifest layout is described in the repository’s [`README.md`](https://github.com/openai/plugins/blob/main/README.md).

## Skill-Level Implementation

Concrete authentication logic resides in the skill files under `plugins/<name>/skills/…`. Each skill includes a "References" section pointing to a markdown file describing the exact flow used by that plugin.

According to the openai/plugins source code, the Zoom plugins demonstrate this pattern clearly:

- The Zoom Apps SDK uses **OAuth 2.0 with Authorization Code and PKCE** for in-client authorization, documented in [`plugins/zoom/skills/zoom-apps-sdk/references/oauth.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/zoom-apps-sdk/references/oauth.md).
- The Zoom REST API handles token exchange and refresh logic in [`plugins/zoom/skills/rest-api/references/authentication.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/rest-api/references/authentication.md).
- The Zoom Video SDK uses **JWT signatures**, detailed in [`plugins/zoom/skills/video-sdk/references/authorization.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/video-sdk/references/authorization.md).

## Supported Authentication Mechanisms

The repository supports multiple authentication patterns to accommodate different third-party service requirements.

### API-Key and Bearer Tokens

**API-Key** authentication is used for simple service-to-service calls where the provider issues a static token. The plugin adds `Authorization: Bearer <token>` to each request header.

This pattern appears throughout the repository, with the Zoom OAuth reference demonstrating the `Authorization` header convention. This method requires no token refresh logic since the key remains static.

### OAuth 2.0 Authorization Code with PKCE

**OAuth 2.0 Authorization Code with PKCE** handles user-delegated access where explicit consent is required. The plugin generates a PKCE challenge, redirects the user to the provider’s authorization endpoint, exchanges the authorization code for an access token, and stores the token for subsequent calls.

In the Zoom Apps SDK implementation, skill code calls `zoomSdk.authorize({ codeChallenge, state })` to initiate the flow. The detailed PKCE implementation is documented in [`plugins/zoom/skills/zoom-apps-sdk/references/oauth.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/zoom-apps-sdk/references/oauth.md).

### OAuth 2.0 Client Credentials

**OAuth 2.0 Client Credentials** (server-to-server) supports background services that act on behalf of the application rather than a user. This flow uses the client ID and secret to obtain a token without user interaction.

The token endpoint accepts `grant_type=client_credentials` and returns an access token for API calls. This pattern is described in [`plugins/zoom/skills/rest-api/concepts/authentication-flows.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/rest-api/concepts/authentication-flows.md) and commonly used for Zoom Webhooks and internal bots.

### JSON Web Tokens (JWT)

**JWT** authentication is used by the legacy Zoom Video SDK and high-performance APIs that require signed requests. The plugin creates a JWT using the SDK key and secret, setting claims such as `iss` (issuer) and `exp` (expiration).

The JWT generation steps are documented in [`plugins/zoom/skills/video-sdk/references/authorization.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/video-sdk/references/authorization.md). Each request includes the token in the `Authorization: JWT <signed_token>` header.

## Authentication Lifecycle

The authentication process follows a strict lifecycle from validation to error handling.

1. **Manifest Validation** – The OpenAI platform validates that the plugin’s manifest lists an accepted authentication type before executing any code.

2. **Token Acquisition** – Skill code initiates the appropriate flow, such as `zoomSdk.authorize()` for in-client OAuth or server-side requests for client credentials.

3. **Token Storage and Refresh** – Access tokens are cached (often in DynamoDB for Zoom implementations) and refreshed before expiry using the `/oauth/token` endpoint with `grant_type=refresh_token`.

4. **Header Injection** – Every outbound HTTP request attaches the appropriate header, either `Authorization: Bearer <access_token>` or `Authorization: JWT <signed_token>`.

5. **Error Handling** – When calls return 401 or 403 status codes, the skill triggers a re-authentication flow as outlined in [`plugins/zoom/skills/oauth/references/oauth-errors.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/oauth/references/oauth-errors.md).

## Implementation Examples

Below are minimal implementations demonstrating each authentication pattern.

### Bearer Token Implementation

```javascript
import fetch from 'node-fetch';

async function callExternalApi(endpoint, apiKey) {
  const res = await fetch(endpoint, {
    headers: { 'Authorization': `Bearer ${apiKey}` },
  });
  return res.json();
}

```

### OAuth 2.0 PKCE Implementation

```javascript
async function startPkceFlow() {
  const challenge = await fetch('/api/auth/challenge').then(r => r.json());
  await zoomSdk.authorize({ 
    codeChallenge: challenge.codeChallenge, 
    state: challenge.state 
  });
  // Listen for the onAuthorized callback to receive the access token
}

```

### OAuth 2.0 Client Credentials Implementation

```javascript
import axios from 'axios';

async function getServerToken(clientId, clientSecret) {
  const resp = await axios.post('https://zoom.us/oauth/token', null, {
    params: { grant_type: 'client_credentials' },
    auth: { username: clientId, password: clientSecret },
  });
  return resp.data.access_token;
}

```

### JWT Implementation

```javascript
import jwt from 'jsonwebtoken';

function makeJwt(sdkKey, sdkSecret) {
  const payload = { 
    iss: sdkKey, 
    exp: Math.floor(Date.now() / 1000) + 3600 
  };
  return jwt.sign(payload, sdkSecret);
}

```

## Summary

- Plugins must declare authentication requirements in `*.codex-plugin/plugin.json` using the `authentication` field to enable runtime validation.
- Skill-level authentication logic is implemented in `plugins/<name>/skills/` directories with detailed flows documented in reference markdown files.
- Supported mechanisms include **API-Key/Bearer tokens**, **OAuth 2.0 (PKCE and Client Credentials)**, and **JWT**, each suited to different integration patterns.
- The authentication lifecycle includes manifest validation, token acquisition, storage with refresh logic, header injection, and error handling via re-authentication flows.

## Frequently Asked Questions

### Where are authentication requirements declared for a plugin?

Authentication requirements are declared in the plugin’s manifest file at `*.codex-plugin/plugin.json`. The `authentication` field specifies the required scheme (such as `api_key`, `oauth2`, or `jwt`), which allows the OpenAI runtime to validate credentials before executing skill code.

### What is the difference between manifest-level and skill-level authentication?

Manifest-level authentication acts as a gateway check—the platform validates that required credentials exist before running any code. Skill-level authentication contains the actual implementation logic, such as calling `zoomSdk.authorize()` or generating JWT signatures, and resides in files under `plugins/<name>/skills/`.

### How does token refresh work in the OpenAI plugins authentication lifecycle?

Tokens are cached in persistent storage (often DynamoDB for Zoom-based plugins) and refreshed before expiration using the provider’s token endpoint with `grant_type=refresh_token`. The refresh logic is typically implemented in `plugins/<name>/skills/rest-api/references/authentication.md` for OAuth-based plugins.

### Which authentication mechanism should I use for server-to-server integrations?

For server-to-server integrations that do not require user consent, use **OAuth 2.0 Client Credentials**. This flow authenticates using only the client ID and secret without user interaction, as documented in [`plugins/zoom/skills/rest-api/concepts/authentication-flows.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/rest-api/concepts/authentication-flows.md).