How to Configure OAuth Providers like Claude Code, Codex, and GitHub Copilot in OmniRoute
To configure OAuth providers in OmniRoute, send a POST request to /api/v1/providers/{providerId}/connections with authType set to "oauth", the provider id, and valid accessToken and refreshToken values; OmniRoute then encrypts, deduplicates, and persists the connection.
OmniRoute unifies LLM routing by storing every provider inside a central catalog. OAuth-only providers such as Claude Code, OpenAI Codex, and GitHub Copilot are defined in src/shared/constants/providers/oauth.ts and registered through a single REST endpoint. Understanding the exact payload structure and how the backend handles encryption and duplicate detection lets you integrate these tools securely without manual database edits.
Where OAuth Providers Are Defined in the OmniRoute Source Code
All OAuth providers live in the constant catalog at src/shared/constants/providers/oauth.ts. Each entry declares the provider id, display name, alias, icon, color, and the subscriptionRisk flag:
// src/shared/constants/providers/oauth.ts
export const OAUTH_PROVIDERS = {
claude: {
id: "claude",
alias: "cc",
name: "Claude Code",
icon: "smart_toy",
color: "#D97757",
subscriptionRisk: true,
riskNoticeVariant: "oauth",
},
antigravity: {
id: "antigravity",
name: "Antigravity",
icon: "rocket_launch",
color: "#F59E0B",
subscriptionRisk: true,
riskNoticeVariant: "oauth",
},
codex: {
id: "codex",
alias: "cx",
name: "OpenAI Codex",
icon: "code",
color: "#3B82F6",
subscriptionRisk: true,
riskNoticeVariant: "oauth",
},
github: { id: "github", alias: "gh", name: "GitHub Copilot", icon: "code", color: "#333333" },
cursor: {
id: "cursor",
alias: "cu",
name: "Cursor IDE",
icon: "edit_note",
color: "#00D4AA",
subscriptionRisk: true,
riskNoticeVariant: "oauth",
},
// …other OAuth providers
};
Because every provider in this object carries riskNoticeVariant: "oauth", the UI renders them under the OAuth Providers tab and displays the corresponding warning icon next to each tile.
Required API Fields for Creating an OAuth Connection
The public API handler lives under src/app/api/v1/providers/[provider]/connections/route.ts. It forwards incoming JSON to createProviderConnection in src/lib/db/providers.ts.
Submit a POST request to:
POST /api/v1/providers/{providerId}/connections
The request body must include the following fields:
authType— Required. Must be the string"oauth"for all providers listed in this guide.provider— Required. The provideridfrom the catalog (e.g.,"claude","github","cursor").accessToken— Required. The OAuth access token returned by the provider’s authorization flow.refreshToken— Required. The token OmniRoute uses for automatic renewal.expiresAt— Optional. ISO-8601 timestamp after which the access token is considered stale.email— Optional. Used for duplicate detection; highly recommended for Codex and Claude.displayName— Optional. Human-readable label (defaults to the email if omitted).providerSpecificData— Optional. Provider-specific JSON such asworkspaceIdfor Codex orprojectIdfor Antigravity.
How to Register a Claude Code OAuth Connection
Use the provider ID claude and alias cc. The following curl command passes the minimal required fields plus an optional display name:
curl -X POST https://my-omniroute.example.com/api/v1/providers/claude/connections \
-H "Content-Type: application/json" \
-d '{
"authType": "oauth",
"provider": "claude",
"accessToken": "ya29.a0AfH6SM....",
"refreshToken": "1//04iZk....",
"expiresAt": "2027-03-01T12:34:56Z",
"email": "alice@example.com",
"displayName": "Alice-Claude",
"providerSpecificData": {}
}'
How to Register a GitHub Copilot OAuth Connection
For GitHub Copilot, set provider to "github" and include the GitHub-issued tokens:
curl -X POST https://my-omniroute.example.com/api/v1/providers/github/connections \
-H "Content-Type: application/json" \
-d '{
"authType": "oauth",
"provider": "github",
"accessToken": "gho_XXXXXXXXXXXXXXXXXXXX",
"refreshToken": "ghr_XXXXXXXXXXXXXXXXXXXX",
"expiresAt": "2027-01-15T08:00:00Z",
"email": "bob@company.com",
"displayName": "Bob-Copilot"
}'
How to Register a Cursor IDE OAuth Connection
Cursor uses the provider ID cursor. IDE-based OAuth providers can also follow the manual import pattern demonstrated in src/app/api/providers/zed/manual-import/route.ts, but the standard REST flow is preferred:
curl -X POST https://my-omniroute.example.com/api/v1/providers/cursor/connections \
-H "Content-Type: application/json" \
-d '{
"authType": "oauth",
"provider": "cursor",
"accessToken": "cursor-access-token",
"refreshToken": "cursor-refresh-token",
"expiresAt": "2026-12-31T23:59:59Z",
"email": "carol@dev.com",
"displayName": "Carol-Cursor"
}'
Duplicate Detection and Encryption Logic
All CRUD operations run through src/lib/db/providers.ts, specifically the createProviderConnection function. Before inserting a row, OmniRoute performs four critical steps:
- Validates the payload.
- Normalizes provider-specific data via
normalizeProviderSpecificData. - Detects duplicates by matching
provider,auth_type, andemail. For Codex, it can also disambiguate byworkspaceIdinsideproviderSpecificData. - Encrypts secret fields through
encryptConnectionFieldsbefore persistence.
If an existing connection matches the same email and provider, the function performs an upsert rather than creating a second row, preventing quota-splitting bugs:
// src/lib/db/providers.ts – creation flow
export async function createProviderConnection(data: JsonRecord) {
const db = getDbInstance() as unknown as DbLike;
const now = new Date().toISOString();
const normalizedProviderSpecificData = normalizeProviderSpecificData(
toStringOrNull(data.provider),
data.providerSpecificData
);
// ---- OAuth duplicate detection (email + workspace) ----
if (data.authType === "oauth" && data.email) {
const existing = db.prepare(
"SELECT * FROM provider_connections WHERE provider = ? AND auth_type = 'oauth' AND email = ?"
).all(data.provider, data.email) as JsonRecord[];
// …additional disambiguation logic omitted for brevity…
if (existing.length) existingRow = existing[0];
}
// If a matching row exists, update it; otherwise insert a new connection.
if (existingRow) { /* …update logic… */ }
else { /* …insert logic… */ }
}
After persistence, OmniRoute calls _reorderConnections to rebuild the routing priority list automatically.
Automatic Token Refresh and Connection Priorities
OmniRoute does not leave tokens to expire silently. The background logic in src/lib/oauth/refresh.ts periodically calls each provider’s token-refresh endpoint. The newly obtained access token is written back to the database via updateProviderConnection, so your routing pipeline stays active without manual re-authentication.
Once the POST succeeds and tokens are refreshed automatically, the connection appears on the Providers page under the OAuth Providers tab. It immediately becomes eligible for model queries through src/app/api/v1/providers/[provider]/models/route.ts.
Summary
- OmniRoute catalogs OAuth providers in
src/shared/constants/providers/oauth.ts, where each entry usesriskNoticeVariant: "oauth"to flag the authentication method. - Register a connection by sending a
POSTto/api/v1/providers/{providerId}/connectionswithauthType: "oauth",accessToken, andrefreshToken. - The backend at
src/lib/db/providers.tsdeduplicates by email and provider, normalizes metadata, and encrypts secrets before storage. - Duplicate credentials trigger an upsert instead of a new row, preventing connection sprawl.
- OmniRoute automatically refreshes tokens via
src/lib/oauth/refresh.tsand re-orders connection priorities after every create or update.
Frequently Asked Questions
How does OmniRoute prevent duplicate OAuth connections?
OmniRoute detects duplicates inside createProviderConnection in src/lib/db/providers.ts by querying provider_connections for a matching provider, auth_type = 'oauth', and email. For Codex, it can also factor in workspaceId from providerSpecificData. If a match exists, the function updates the existing row instead of inserting a new one.
Does OmniRoute support automatic OAuth token refresh?
Yes. The system runs periodic refresh logic defined in src/lib/oauth/refresh.ts. It exchanges the stored refresh token for a new access token and persists the result through updateProviderConnection, keeping the connection alive without user intervention.
What provider-specific data can I include for Codex or Antigravity?
You can pass a JSON object in the providerSpecificData field. For OpenAI Codex, this may include a workspaceId. For Antigravity, it may include a projectId. OmniRoute normalizes this data through normalizeProviderSpecificData before writing it to the database.
Where can I verify that my OAuth connection was created successfully?
After the API returns success, the connection appears in the Providers page of the OmniRoute UI under the OAuth Providers tab. You can also verify programmatically by querying GET /api/v1/providers/{providerId}/models, which reads active connections in src/app/api/v1/providers/[provider]/models/route.ts to determine reachable models.
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 →