Authentication Requirements for Plugins in the OpenAI Repository: Manifest and Skill Implementation
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.
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. - The Zoom REST API handles token exchange and refresh logic in
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.
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.
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 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. 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.
-
Manifest Validation – The OpenAI platform validates that the plugin’s manifest lists an accepted authentication type before executing any code.
-
Token Acquisition – Skill code initiates the appropriate flow, such as
zoomSdk.authorize()for in-client OAuth or server-side requests for client credentials. -
Token Storage and Refresh – Access tokens are cached (often in DynamoDB for Zoom implementations) and refreshed before expiry using the
/oauth/tokenendpoint withgrant_type=refresh_token. -
Header Injection – Every outbound HTTP request attaches the appropriate header, either
Authorization: Bearer <access_token>orAuthorization: JWT <signed_token>. -
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.
Implementation Examples
Below are minimal implementations demonstrating each authentication pattern.
Bearer Token Implementation
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
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
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
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.jsonusing theauthenticationfield 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →