How OAuth Authentication Works for Claude Code, Cursor, and Cline in OmniRoute

OmniRoute implements OAuth authentication for Claude Code, Cursor, and Cline using the standard Authorization Code flow with PKCE, with provider-specific extensions for account metadata retrieval.

The diegosouzapw/OmniRoute repository provides a unified OAuth layer that handles authentication across three popular AI coding assistants. All three providers authenticate against Anthropic's OAuth infrastructure via src/lib/oauth/providers/claude.ts, while Cursor and Cline reuse the same core logic through thin wrapper modules.

OAuth Flow Overview: Authorization Code with PKCE

Every provider follows the same six-step sequence. The implementation in src/lib/oauth/providers/claude.ts serves as the foundation, with Cursor and Cline inheriting or reusing these methods.

Step 1: Build the Authorization URL

The buildAuthUrl method constructs the initial redirect to Anthropic's OAuth endpoint.

// src/lib/oauth/providers/claude.ts#L82-L100
const authUrl = provider.buildAuthUrl(
  provider.config,
  "http://localhost:3000/callback",
  state,           // cryptographically random UUID
  codeChallenge,   // PKCE S256 code challenge
);

Key parameters include:

  • client_id — registered application identifier
  • code_challenge — PKCE challenge for proof key
  • scope — requested permissions (typically offline_access)
  • prompt=login — forces re-authentication to prevent token reuse
  • state — CSRF protection token

Step 2: User Authorization

The user completes authentication in their browser. Anthropic redirects back to the configured callback with an authorization code and the original state parameter for validation.

Step 3: Exchange Code for Tokens

The exchangeToken method posts to Anthropic's token endpoint.

// src/lib/oauth/providers/claude.ts#L103-L126
const tokenResponse = await provider.exchangeToken(
  provider.config,
  authCode,        // from callback query parameter
  redirectUri,
  codeVerifier,    // original PKCE verifier
  state,
);

The response contains access_token, refresh_token, expires_in, and scope.

Step 4: Post-Exchange Bootstrap (Claude Code Only)

Claude Code requires an additional API call to retrieve account metadata.

// src/lib/oauth/providers/claude.ts#L135-L140
const bootstrapData = await provider.postExchange(tokenResponse);
// POST https://api.anthropic.com/api/claude_cli/bootstrap
// Authorization: Bearer {access_token}

This endpoint returns account_uuid, organization_uuid, email, and subscription plan — data not present in the standard OAuth token response.

Step 5: Map Tokens to OmniRoute's Internal Format

The mapTokens method normalizes provider responses into a consistent connection object.

// src/lib/oauth/providers/claude.ts#L140-L168
const connectionInfo = provider.mapTokens(
  tokenResponse,
  await provider.postExchange(tokenResponse) // null for Cursor/Cline
);

The resulting structure includes:

  • Standard OAuth fields: accessToken, refreshToken, expiresIn, scope
  • Identity fields: email
  • Provider-specific data: cliUserID, accountUUID, organizationName, plan

Step 6: Token Refresh

Refresh operations reuse exchangeToken logic with grant_type=refresh_token. The same mapping pipeline updates stored credentials.

Provider-Specific Implementations

Claude Code OAuth Authentication

Claude Code is the most complex provider due to the bootstrap requirement. The full implementation resides in src/lib/oauth/providers/claude.ts with three key methods:

  • buildAuthUrl — constructs Anthropic authorization URL
  • exchangeToken — performs code exchange
  • postExchange — fetches /claude_cli/bootstrap metadata
  • mapTokens — merges OAuth and bootstrap data

The bootstrap response is cached as providerSpecificData for downstream authorization decisions.

Cursor OAuth Authentication

Cursor reuses the generic flow without the Claude-specific bootstrap call. The implementation in src/lib/oauth/providers/cursor.ts mirrors claude.ts but omits postExchange. Token response fields alone satisfy OmniRoute's connection requirements.

// Cursor provider imports and reexports from claude.ts
// with postExchange overridden to return null

Cline OAuth Authentication

Cline follows the same pattern as Cursor. The src/lib/oauth/providers/cline.ts module is a thin wrapper that delegates to the generic OAuth helpers registered in the provider index.

Complete OAuth Implementation Example

import { getProvider } from "@/lib/oauth/providers";

// Initialize provider (claude | cursor | cline)
const provider = getProvider("cursor");

// Generate PKCE pair
const codeVerifier = crypto.randomBytes(32).toString("base64url");
const codeChallenge = await sha256(codeVerifier);

// Step 1: Build authorization URL
const state = crypto.randomUUID();
const authUrl = provider.buildAuthUrl(
  provider.config,
  process.env.OAUTH_REDIRECT_URI,
  state,
  codeChallenge,
);

// After user returns with authorization code...
// Step 2-3: Exchange for tokens
const tokenResponse = await provider.exchangeToken(
  provider.config,
  req.query.code,
  process.env.OAUTH_REDIRECT_URI,
  codeVerifier,
  req.query.state,
);

// Step 4-5: Normalize and store
const extras = await provider.postExchange(tokenResponse);
const connection = provider.mapTokens(tokenResponse, extras);

await db.connections.insert({
  provider: "cursor",
  ...connection,
});

Provider Registration

All three providers are declared in src/shared/constants/providers/oauth.ts:

export const OAUTH_PROVIDERS = {
  claude: {
    authType: "oauth",
    module: "@/lib/oauth/providers/claude",
    endpoints: {
      authorize: "https://auth.anthropic.com/oauth/authorize",
      token: "https://auth.anthropic.com/oauth/token",
    },
  },
  cursor: { /* inherits claude endpoints */ },
  cline: { /* inherits claude endpoints */ },
} as const;

The getProvider factory in src/lib/oauth/providers/index.ts loads the correct module based on the provider ID.

Summary

  • All three providers use Authorization Code with PKCE against Anthropic's OAuth infrastructure
  • Claude Code uniquely requires a bootstrap call to /claude_cli/bootstrap for account metadata
  • Cursor and Cline reuse the generic flow without provider-specific extensions
  • Core implementation lives in src/lib/oauth/providers/claude.ts with thin wrappers for the other providers
  • Token mapping produces a normalized connection object with providerSpecificData for downstream use

Frequently Asked Questions

What OAuth grant type does OmniRoute use for Claude Code, Cursor, and Cline?

OmniRoute uses the Authorization Code grant with PKCE (Proof Key for Code Exchange). This is the modern standard for native and browser-based applications. The PKCE code_challenge prevents authorization code interception attacks. All three providers implement this identically in src/lib/oauth/providers/claude.ts.

Why does Claude Code require a separate bootstrap API call?

The bootstrap endpoint at https://api.anthropic.com/api/claude_cli/bootstrap returns account and organization metadata that Anthropic does not include in the OAuth token response. This includes account_uuid, organization_uuid, email, and subscription plan. OmniRoute caches this as providerSpecificData for authorization and feature-gating decisions. Cursor and Cline do not need this call because their use cases do not require organization-level metadata.

How does OmniRoute handle token refresh for these providers?

Refresh operations reuse the same exchangeToken method with grant_type=refresh_token. The stored refresh_token from the initial connection is posted to Anthropic's token endpoint. The refreshed tokens flow through the identical mapTokens pipeline, updating the connection record with new access and refresh tokens. This ensures consistent data shapes across initial grants and refreshes.

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 →