How to Configure OAuth Providers with OmniRoute's 22 Provider Modules

OmniRoute centralizes OAuth provider configuration in src/lib/oauth/constants/oauth.ts and maps them to 22 modular LLM providers via open-sse/config/providerRegistry.ts, enabling PKCE or device-code flows without embedding secrets in source code.

OmniRoute is an open-source routing layer that unifies access to multiple LLM providers through a single OpenAI-compatible API. To configure OAuth providers with OmniRoute, you modify a single constants file to define PKCE parameters and register the provider in the centralized registry, allowing the routing engine to automatically handle token lifecycle management across all 22 supported modules.

Centralized OAuth Configuration File

All OAuth provider definitions live in src/lib/oauth/constants/oauth.ts. This file exports configuration objects that specify the data required for PKCE or device-code flows.

Each configuration object contains:

  • clientId – Resolved dynamically via resolvePublicCred() to prevent literal secrets in source control
  • authorizeUrl and tokenUrl – The OAuth provider's endpoint URLs
  • scopes – Provider-specific OAuth scopes (e.g., openid, offline_access)
  • extraParams – Additional query parameters such as prompt=login for multi-account support
  • Optional fieldsuserInfoUrl, clientSecret, or deviceCodeUrl for device-code flows

The provider registry imports these constants, creating a single source of truth for all 22 modules.

Registering a New OAuth Provider

Adding a new OAuth provider to OmniRoute requires four specific steps:

  1. Create the configuration export.
    Define a constant in src/lib/oauth/constants/oauth.ts using resolvePublicCred() to inject the client ID from environment variables.

  2. Update the provider registry.
    Add an entry to open-sse/config/providerRegistry.ts specifying id, name, format (typically "openai" for OAuth providers), baseUrl, and point the auth field to your exported config. Include the array of available models with their id, name, and maxTokens.

  3. Configure the executor (if needed).
    Most providers reuse the generic OAuthExecutor located in open-sse/executors/oauthExecutor.ts. If the provider requires custom request handling, create a new executor under open-sse/executors/ and reference it in the registry entry.

  4. Write unit tests.
    Add tests under tests/unit/ that import the registry entry and assert OAuth fields are correctly wired, ensuring the token refresh logic integrates properly.

How the 22 Modules Consume OAuth Configs

When a request targets any of the 22 OAuth-enabled providers (e.g., model: "claude-2"), OmniRoute's pipeline executes four distinct stages:

  • Routingopen-sse/services/combo.ts lookups the model in open-sse/config/providerRegistry.ts. If the entry's auth field contains an OAuth configuration, the router flags the request for token management.

  • Token Acquisitionsrc/lib/oauth/tokenRefreshService.ts retrieves the provider's clientId, authorizeUrl, and scopes, then executes the PKCE or device-code flow. It stores the resulting access token on the connection record.

  • Execution – The OAuthExecutor (or a provider-specific executor) attaches the bearer token to outbound requests via the Authorization: Bearer <access_token> header.

  • Translation – Response translators (such as open-sse/translator/claude.ts) process the upstream payload unchanged, as the authentication layer remains transparent to response formatting.

OmniRoute's 22 OAuth Provider Modules

The current release ships 22 OAuth-enabled provider modules, with key configurations defined in src/lib/oauth/constants/oauth.ts including:

  • ClaudeCLAUDE_CONFIG
  • Codex (OpenAI)CODEX_CONFIG
  • QoderQODER_CONFIG
  • CodeBuddy CNCODEBUDDY_CN_CONFIG
  • Grok CLIGROK_CLI_CONFIG
  • Grok BuildGROK_BUILD_OAUTH_CONFIG
  • xAI APIXAI_OAUTH_CONFIG
  • OpenferenceOPENFERENCE_CONFIG
  • Kimi CodingKIMI_CODING_CONFIG
  • KiloCodeKILOCODE_CONFIG
  • ClineCLINE_CONFIG
  • AntigravityANTIGRAVITY_CONFIG

Additional providers utilize the generic OAuth executor infrastructure, bringing the total to 22 modular integrations.

Practical Implementation Example

The following example demonstrates adding a hypothetical "MyAI" provider to OmniRoute's ecosystem:

// src/lib/oauth/constants/oauth.ts
import { resolvePublicCred } from "@omniroute/open-sse/utils/publicCreds.ts";

export const MYAI_CONFIG = {
  clientId: resolvePublicCred("myai_id", "MYAI_OAUTH_CLIENT_ID"),
  authorizeUrl: "https://auth.myai.com/oauth/authorize",
  tokenUrl: "https://auth.myai.com/oauth/token",
  scopes: ["openid", "profile", "email", "offline_access"],
  codeChallengeMethod: "S256",
};
// open-sse/config/providerRegistry.ts
import { REGISTRY } from "@omniroute/open-sse/config/providerRegistry.ts";
import { MYAI_CONFIG } from "../../src/lib/oauth/constants/oauth.ts";

REGISTRY["myai"] = {
  id: "myai",
  name: "MyAI",
  format: "openai",
  baseUrl: "https://api.myai.com/v1",
  auth: MYAI_CONFIG,
  models: [
    { id: "myai-chat", name: "MyAI Chat", maxTokens: 8192 },
  ],
};
// Client request
await fetch("http://localhost:20128/v1/chat/completions", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "myai-chat",
    messages: [{ role: "user", content: "Hello!" }],
  }),
});

Because the configuration uses resolvePublicCred(), you store the actual MYAI_OAUTH_CLIENT_ID in .env.example, keeping credentials out of the repository while allowing runtime injection.

Summary

  • Centralized configuration – All OAuth parameters for the 22 modules reside in src/lib/oauth/constants/oauth.ts, preventing credential leakage through resolvePublicCred().
  • Registry-based routingopen-sse/config/providerRegistry.ts maps model IDs to OAuth configs, enabling automatic token lifecycle management without code changes to the routing layer.
  • Four-stage pipeline – Requests flow through routing (combo.ts), token acquisition (tokenRefreshService.ts), execution (OAuthExecutor), and translation layers seamlessly.
  • Modular expansion – Adding new providers requires only a registry entry and configuration export; the infrastructure handles PKCE flows, circuit-breaker back-off, and per-connection cooldowns automatically.

Frequently Asked Questions

How does OmniRoute prevent OAuth client secrets from appearing in source code?

OmniRoute uses the resolvePublicCred() utility function imported from @omniroute/open-sse/utils/publicCreds.ts to inject client IDs at runtime. You define environment variable names (such as MYAI_OAUTH_CLIENT_ID) in your configuration while storing actual values in .env.example or your deployment environment, ensuring no literal secrets exist in the repository.

Can I use device-code authentication instead of PKCE for OmniRoute providers?

Yes. The oauth.ts constants file supports optional fields including deviceCodeUrl and clientSecret. When these fields are present, src/lib/oauth/tokenRefreshService.ts automatically executes the device-code flow instead of PKCE, storing the resulting access token on the connection record for bearer token authentication.

Do I need to create a custom executor for every new OAuth provider?

No. Most of the 22 modules reuse the generic OAuthExecutor. You only need to create a custom executor under open-sse/executors/ if the provider requires non-standard request handling or authentication mechanisms that deviate from the standard OAuth 2.0 bearer token pattern.

Which file handles the actual token refresh logic for all 22 modules?

The src/lib/oauth/tokenRefreshService.ts file contains the core logic for token acquisition and refresh across all providers. It reads the provider-specific configuration from oauth.ts, manages the PKCE or device-code exchange, and maintains token state on connection records, insulating the routing and execution layers from OAuth complexity.

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 →