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

> Easily configure OAuth providers with OmniRoute. Integrate 22 modular LLM providers using PKCE or device-code flows securely, without embedding secrets.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-24

---

**OmniRoute centralizes OAuth provider configuration in [`src/lib/oauth/constants/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts) and maps them to 22 modular LLM providers via [`open-sse/config/providerRegistry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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 fields** – `userInfoUrl`, `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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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:

- **Routing** – [`open-sse/services/combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/combo.ts) lookups the model in [`open-sse/config/providerRegistry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/config/providerRegistry.ts). If the entry's `auth` field contains an OAuth configuration, the router flags the request for token management.

- **Token Acquisition** – [`src/lib/oauth/tokenRefreshService.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts) including:

- **Claude** – `CLAUDE_CONFIG`
- **Codex (OpenAI)** – `CODEX_CONFIG`
- **Qoder** – `QODER_CONFIG`
- **CodeBuddy CN** – `CODEBUDDY_CN_CONFIG`
- **Grok CLI** – `GROK_CLI_CONFIG`
- **Grok Build** – `GROK_BUILD_OAUTH_CONFIG`
- **xAI API** – `XAI_OAUTH_CONFIG`
- **Openference** – `OPENFERENCE_CONFIG`
- **Kimi Coding** – `KIMI_CODING_CONFIG`
- **KiloCode** – `KILOCODE_CONFIG`
- **Cline** – `CLINE_CONFIG`
- **Antigravity** – `ANTIGRAVITY_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:

```typescript
// 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",
};

```

```typescript
// 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 },
  ],
};

```

```typescript
// 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts), preventing credential leakage through `resolvePublicCred()`.
- **Registry-based routing** – [`open-sse/config/providerRegistry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-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`](https://github.com/diegosouzapw/OmniRoute/blob/main/combo.ts)), token acquisition ([`tokenRefreshService.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/oauth.ts) constants file supports optional fields including `deviceCodeUrl` and `clientSecret`. When these fields are present, [`src/lib/oauth/tokenRefreshService.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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.