Skip to content

[FEATURE]: Support OAuth 2.0 client_credentials for configured providers #24084

Closed as not planned

Description

@benjaminwestern

[x] I have verified this feature I'm about to request hasn't been suggested before.

Would you consider adding opt-in OAuth 2.0 client_credentials support for configured providers at the provider fetch layer?

I am opening this as an issue first because this seems like a core/runtime feature and I wanted to check whether this direction is useful before opening a PR.

Why this is important to us

We are looking at a large enterprise rollout of OpenCode through a new Enterprise LLM Gateway that uses standard OAuth 2.0 client_credentials authentication.

Without something built into the provider path, the likely alternative for us is maintaining custom internal plugin/auth workarounds for what is otherwise a standard enterprise gateway pattern. We are hoping a small built-in capability here could avoid that and also help others using similar enterprise gateways.

Environment-wise, this is for an OpenAI-compatible enterprise gateway setup in front of internal/provider LLM access, similar to patterns commonly seen with Apigee X, Azure APIM, Okta, Keycloak, Kong, and similar brokers.

The gap we are hitting

From looking through the current code, I do not think provider-side client_credentials support exists today.

The current provider OAuth path seems mainly oriented around interactive flows such as:

  • plugin-defined auth methods
  • browser or device login
  • persisted refresh / access / expires state

That is a poor fit for gateways that only support:

  • grant_type=client_credentials
  • client_id
  • client_secret
  • short-lived access_token
  • no refresh_token

In our case, the expected lifecycle is just:

  1. request a token with grant_type=client_credentials
  2. use the returned bearer token
  3. request a new token when it expires or is rejected

What I am asking for

The smallest change that seems useful would be:

  • provider-local and config-driven
  • non-interactive
  • no browser
  • no callback server
  • no /connect or auth login
  • no custom plugin required for the standard case
  • in-memory token caching only
  • token re-acquisition on expiry
  • one retry on 401 or explicit invalid-token responses

A config shape like this would cover the case:

{
  "provider": {
    "corp-openai": {
      "name": "Corp OpenAI",
      "npm": "@ai-sdk/openai-compatible",
      "api": "https://gateway.example.com/openai/v1",
      "options": {
        "oauth": {
          "grantType": "client_credentials",
          "tokenUrl": "https://auth.example.com/oauth2/token",
          "clientId": "${APIGEE_CLIENT_ID}",
          "clientSecret": "${APIGEE_CLIENT_SECRET}",
          "clientAuthMethod": "client_secret_basic",
          "scope": "llm.invoke",
          "audience": "https://gateway.example.com",
          "resource": "https://gateway.example.com"
        }
      }
    }
  }
}

Why I think the provider fetch layer is the right place

packages/opencode/src/provider/provider.ts seems like the best first integration point because it already wraps provider fetch and centralises request-time behaviour.

That seems like a better first fit than:

  • packages/opencode/src/auth/index.ts, which appears to assume refresh / access / expires
  • packages/opencode/src/provider/auth.ts, which appears tied to interactive/plugin auth
  • packages/opencode/src/cli/cmd/providers.ts, which appears focused on browser/code login flows

I also noticed packages/opencode/src/mcp/auth.ts and packages/opencode/src/mcp/oauth-provider.ts as useful future references, but I would not want a broader provider/MCP OAuth redesign to block a small first step here.

What would meet our need

This would solve our use case if:

  • a configured provider can authenticate with grant_type=client_credentials
  • no refresh_token is required
  • no browser or callback server is used
  • tokens are re-acquired automatically when expired
  • one retry is attempted on 401 or explicit invalid-token responses
  • no custom plugin is required for the standard case
  • existing interactive provider auth flows remain unchanged

Related issues

The closest issue I found was:

Other adjacent issues that seemed relevant were:

A few precedent PRs that made this seem potentially reasonable upstream were:

Reference implementation

I also put together a small proof of concept in my fork in case it is useful as a reference:

  • https://github.com/benjaminwestern/opencode/tree/feat/client-credentials

I am intentionally opening an issue first instead of immediately opening a PR, because I do not want to add noise before knowing whether this direction is actually useful or wanted upstream.

Transparency

For transparency: I built the proof of concept by cross-checking proposals from Gemini 3.1 Pro Preview, Kimi k2.6, and GPT-5.4 xhigh to try to get to the smallest functionally sound implementation. The related issues/PRs were scanned for relevance with GPT-5.4 high. This issue draft was co-written with Gemini 3.1 Flash Lite Preview and then edited by hand by me.

If this direction seems reasonable, I would be happy to refine the approach or open a small follow-up PR after feedback.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 24, 2026
  2. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  3. stephane-segning commented on Aug 10, 2026

    @stephane-segning

    For those who're having the same issue, I implemented a plugin to help => https://www.npmjs.com/package/@vymalo/opencode-oauth2

  4. github-actions commented on Oct 11, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions