# OpenAI Plugin Authentication Types: Three Methods to Secure API Endpoints

> Explore OpenAI plugin authentication types: none, service_http, and user_http. Secure your API endpoints effectively with these three distinct methods defined in the plugin manifest.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: deep-dive
- Published: 2026-07-12

---

**OpenAI plugins support three distinct authentication models—`none`, `service_http`, and `user_http`—defined in the plugin manifest to control how credentials are obtained and injected into API requests.**

The `openai/plugins` repository provides a standardized framework for securing plugin endpoints. These plugin authentication options determine whether requests are sent publicly, signed with static service keys, or authorized via user-specific OAuth 2.0 flows.

## The Three Plugin Authentication Models

OpenAI plugins declare their security requirements through the `auth` field in [`manifest.json`](https://github.com/openai/plugins/blob/main/manifest.json). Each model dictates how the ChatGPT runtime handles credentials before forwarding requests to your backend.

### None (Public Endpoints)

The `none` type indicates that the plugin exposes **public endpoints** requiring no authentication. The ChatGPT runtime forwards requests without adding any authorization headers.

Use this model for simple data sources, public information feeds, or demo plugins where data does not require protection. In [`manifest.json`](https://github.com/openai/plugins/blob/main/manifest.json), configure it as:

```json
{
  "auth": {
    "type": "none"
  }
}

```

### Service HTTP (API Keys)

The `service_http` type enables plugins to authenticate using **static API keys** stored in the plugin's configuration. According to the implementation in [`plugins/common/auth/service_http.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/service_http.py), the runtime injects the token into outgoing requests—typically as an `Authorization: Bearer <token>` header—without exposing the secret to end users.

This approach suits single-tenant APIs or internal backends where the plugin acts as a trusted client. The manifest configuration includes:

```json
{
  "auth": {
    "type": "service_http",
    "authorization_type": "Bearer",
    "verification_tokens": {
      "openai": "YOUR_OPENAI_VERIFICATION_TOKEN"
    }
  }
}

```

In your plugin code, retrieve the key from environment variables injected by the runtime:

```python
import os
import requests

API_KEY = os.getenv("SERVICE_API_KEY")

def fetch_secure_data():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    resp = requests.get("https://api.example.com/secure", headers=headers)
    resp.raise_for_status()
    return resp.json()

```

### User HTTP (OAuth 2.0)

The `user_http` type implements **OAuth 2.0 authentication** for user-specific data access. As implemented in [`plugins/common/auth/oauth.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth.py), the runtime orchestrates the consent flow: redirecting users to the provider's authorization page, exchanging codes for tokens, and automatically injecting access tokens into subsequent requests.

This model supports multiple grant types handled in [`plugins/common/auth/oauth_flow.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth_flow.py):

- **Authorization Code** (standard web flow)
- **PKCE** (for mobile and single-page applications)
- **Client Credentials** (service-to-service on behalf of the app)
- **Device Code** (for devices without browsers)

Use `user_http` when your plugin acts on behalf of a user, such as accessing calendars, email, or CRM systems. The manifest requires OAuth endpoint configuration:

```json
{
  "auth": {
    "type": "user_http",
    "authorization_type": "Bearer",
    "oauth": {
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "scopes": ["read", "write"],
      "authorization_endpoint": "https://provider.com/oauth/authorize",
      "token_endpoint": "https://provider.com/oauth/token"
    }
  }
}

```

The implementation follows standard OAuth patterns:

```python
import os
import requests
from urllib.parse import urlencode

def build_consent_url():
    params = {
        "client_id": os.getenv("OAUTH_CLIENT_ID"),
        "redirect_uri": "https://my-plugin.example.com/callback",
        "response_type": "code",
        "scope": "read write",
        "state": "random_csrf_token"
    }
    return f"https://provider.com/oauth/authorize?{urlencode(params)}"

def exchange_code_for_token(code):
    data = {
        "client_id": os.getenv("OAUTH_CLIENT_ID"),
        "client_secret": os.getenv("OAUTH_CLIENT_SECRET"),
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": "https://my-plugin.example.com/callback"
    }
    resp = requests.post("https://provider.com/oauth/token", data=data)
    resp.raise_for_status()
    return resp.json()["access_token"]

def fetch_user_data(access_token):
    headers = {"Authorization": f"Bearer {access_token}"}
    resp = requests.get("https://api.provider.com/me", headers=headers)
    resp.raise_for_status()
    return resp.json()

```

## Core Authentication Implementation Files

The `openai/plugins` repository organizes authentication logic into specific modules that handle credential injection and token management according to the OpenAPI specification.

### [`plugins/common/auth/service_http.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/service_http.py)

This file contains the runtime implementation for the `service_http` model. It manages the injection of static service tokens into request headers and ensures that secrets configured in the plugin environment are never transmitted to the client.

### [`plugins/common/auth/oauth.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth.py)

The core OAuth 2.0 logic resides here, handling authorization URL generation, token exchange with providers, and automatic refresh of expired tokens. This module manages the secure storage of user access tokens obtained through the consent flow.

### [`plugins/common/auth/oauth_flow.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth_flow.py)

Higher-level helpers in this file support the various OAuth grant types. It abstracts the differences between Authorization Code, PKCE, Client Credentials, and Device Code flows, providing a unified interface for the runtime to obtain user-specific credentials.

### [`openapi.yaml`](https://github.com/openai/plugins/blob/main/openapi.yaml)

The OpenAPI specification includes `security` objects that map to the authentication type declared in [`manifest.json`](https://github.com/openai/plugins/blob/main/manifest.json). These definitions ensure that the ChatGPT runtime knows which endpoints require authorization and what type of credentials to provide.

## Summary

- **OpenAI plugin authentication** offers three models: `none` for public data, `service_http` for static API keys, and `user_http` for OAuth 2.0 user consent flows.
- The `auth.type` field in [`manifest.json`](https://github.com/openai/plugins/blob/main/manifest.json) declares which model the plugin uses, determining how the ChatGPT runtime prepares requests.
- **`service_http`** credentials are stored in the plugin configuration and injected by the code in [`plugins/common/auth/service_http.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/service_http.py), keeping secrets hidden from users.
- **`user_http`** supports Authorization Code, PKCE, Client Credentials, and Device Code grants through the implementation in [`plugins/common/auth/oauth.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth.py) and [`oauth_flow.py`](https://github.com/openai/plugins/blob/main/oauth_flow.py).
- All authentication configurations must align with the `security` definitions in [`openapi.yaml`](https://github.com/openai/plugins/blob/main/openapi.yaml) to ensure proper credential mapping.

## Frequently Asked Questions

### What is the difference between service_http and user_http authentication?

**`service_http`** uses static API keys associated with the plugin itself, not individual users. The runtime stores these secrets and injects them into every request. **`user_http`** implements OAuth 2.0 to obtain per-user access tokens, requiring explicit user consent through a provider's authorization page before the plugin can access their data.

### Which OAuth 2.0 grant types does the OpenAI plugin system support?

According to the implementation in [`plugins/common/auth/oauth_flow.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth_flow.py), the platform supports **Authorization Code** for standard web flows, **PKCE** for mobile and browser-based clients, **Client Credentials** for service-to-service authentication, and **Device Code** for input-constrained devices. The manifest configuration determines which flow the runtime initiates.

### Can I implement plugin authentication without requiring any credentials?

Yes. By setting `"type": "none"` in the [`manifest.json`](https://github.com/openai/plugins/blob/main/manifest.json) `auth` object, you create a plugin that accesses public endpoints without authentication. This is suitable for open data sources and demo applications where no sensitive information is transmitted.

### How does the ChatGPT runtime handle token security?

For `service_http`, the runtime stores API keys in the plugin's backend environment, never exposing them to the frontend or end users. For `user_http`, access tokens obtained through OAuth flows are managed securely by the runtime and injected into requests server-side, with refresh logic handled automatically by [`plugins/common/auth/oauth.py`](https://github.com/openai/plugins/blob/main/plugins/common/auth/oauth.py) to maintain sessions without storing long-lived credentials.