How to Set Up OAuth with PKCE for OmniRoute Providers Like GitHub Copilot

OmniRoute implements OAuth Authorization Code Flow with PKCE (Proof Key for Code Exchange) through a centralized utility in src/lib/oauth/utils/pkce.ts, which providers like GitHub Copilot call automatically to generate secure code verifiers and challenges.

Setting up OAuth with PKCE for OmniRoute providers protects against authorization code interception attacks by ensuring only the original client can exchange the code for tokens. The implementation is provider-agnostic—any OmniRoute provider requiring PKCE, including GitHub Copilot and GitHub Enterprise Copilot, imports the same core utilities. This guide walks through the PKCE generation process, how providers integrate it, and complete code examples for building authorization URLs and exchanging tokens.

What Is PKCE and Why OmniRoute Uses It

PKCE (RFC 7636) extends the OAuth 2.0 Authorization Code Flow to prevent malicious applications from intercepting authorization codes and exchanging them for access tokens. It works by having the client generate a secret verifier that is never transmitted until the token exchange step.

OmniRoute's PKCE implementation follows the specification exactly:

  • Code verifier: A random string between 43-128 characters
  • Code challenge: SHA-256 hash of the verifier, Base64URL-encoded
  • State parameter: CSRF protection via cryptographically random token

The generated values are transient—no secrets persist in the repository or database.

Core PKCE Utilities in OmniRoute

The PKCE engine lives in src/lib/oauth/utils/pkce.ts. Four functions handle the complete workflow:

Function Purpose
generateCodeVerifier() Creates high-entropy random string (43-128 bytes)
generateCodeChallenge(verifier) Returns SHA-256 hash, Base64URL-encoded
generateState() Generates CSRF protection token
generatePKCE() Convenience wrapper returning all three values

These utilities are exported through src/lib/oauth/providers.ts, making them available to every provider implementation.

How GitHub Copilot Uses PKCE

The GitHub Enterprise Copilot provider (src/lib/oauth/providers/ghe-copilot.ts) demonstrates the full PKCE integration. When initiating a device-code or authorization-code flow, the provider:

  1. Calls generatePKCE() from the central utilities
  2. Embeds codeChallenge and state in the authorization request
  3. Stores codeVerifier for the subsequent token exchange
  4. Sends code_verifier during the POST to the token endpoint

The provider also normalizes custom GitHub Enterprise URLs and maps returned tokens into OmniRoute's internal format.

Complete Implementation Examples

Generating PKCE Data

// src/lib/oauth/utils/pkce.ts - Core generation functions
import { generatePKCE } from "@/src/lib/oauth/utils/pkce";

const pkce = generatePKCE();
// Returns:
// {
//   codeVerifier: "K2Oa6r8d9J3w...128-chars...",
//   codeChallenge: "E9Melhoa2OwvFrEMT8v5...",
//   state: "random_csrf_token_..."
// }

Building the Authorization URL

import { generatePKCE } from "@/src/lib/oauth/utils/pkce";
import { copilot } from "@/src/lib/oauth/providers/ghe-copilot";

const pkce = generatePKCE();

const authUrl = new URL("https://github.com/login/oauth/authorize");
authUrl.searchParams.set("client_id", copilot.config.clientId);
authUrl.searchParams.set("scope", copilot.config.scopes.join(" "));
authUrl.searchParams.set("code_challenge", pkce.codeChallenge);
authUrl.searchParams.set("code_challenge_method", "S256");
authUrl.searchParams.set("state", pkce.state);
authUrl.searchParams.set("redirect_uri", copilot.config.redirectUri);

// Redirect user to authUrl.toString()

Exchanging the Authorization Code

const tokenResponse = await fetch("https://github.com/login/oauth/access_token", {
  method: "POST",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded",
    "Accept": "application/json"
  },
  body: new URLSearchParams({
    client_id: copilot.config.clientId,
    code: receivedAuthorizationCode,        // From callback
    code_verifier: pkce.codeVerifier,       // Original verifier
    redirect_uri: copilot.config.redirectUri,
    grant_type: "authorization_code"
  })
});

const tokens = await tokenResponse.json();
// { access_token, token_type, scope }

GitHub Enterprise Copilot Variant

For GitHub Enterprise deployments, the same pattern applies with a configurable base URL:

import { copilot } from "@/src/lib/oauth/providers/ghe-copilot";

// Provider normalizes gheUrl from connection configuration
const baseUrl = copilot.normalizeUrl(gheUrl); // e.g., "https://github.mycompany.com"

const deviceCodeUrl = `${baseUrl}/login/device/code`;
const tokenUrl = `${baseUrl}/login/oauth/access_token`;

// PKCE generation and exchange identical to public GitHub

API Endpoint Integration

The OAuth flow is triggered via src/app/api/oauth/[provider]/[action]/route.ts. This endpoint:

  1. Validates the provider name against registered providers
  2. Generates PKCE parameters via generatePKCE()
  3. Returns the authorization URL with embedded challenge and state
  4. Stores the verifier securely for the callback phase

No PKCE secrets are logged or exposed to the client beyond the required challenge parameter.

Summary

  • OmniRoute centralizes PKCE logic in src/lib/oauth/utils/pkce.ts with generatePKCE(), generateCodeVerifier(), and generateCodeChallenge()
  • Providers import these utilities through src/lib/oauth/providers.ts and call them automatically during OAuth initialization
  • GitHub Copilot and GitHub Enterprise Copilot implement identical PKCE patterns, differing only in base URL configuration
  • The code_verifier is never transmitted until the token exchange, preventing interception attacks
  • All PKCE values are ephemeral—no secrets are persisted in the codebase or database

Frequently Asked Questions

Does OmniRoute store PKCE secrets in the database?

No. The codeVerifier, codeChallenge, and state are generated per-request and held only in memory or short-lived session storage during the OAuth flow. The source code in src/lib/oauth/utils/pkce.ts performs pure cryptographic generation without persistence.

Can I use PKCE with providers other than GitHub Copilot?

Yes. Any OmniRoute provider can enable PKCE by importing generatePKCE from the central utilities. The pattern in src/lib/oauth/providers/ghe-copilot.ts serves as the reference implementation for adding PKCE to custom providers.

What happens if the code verifier is lost before token exchange?

The authorization code cannot be redeemed. Per the OAuth PKCE specification, the token endpoint verifies that the code_verifier matches the original code_challenge. OmniRoute's flow design keeps the verifier available through the callback phase, typically via server-side session storage.

Is PKCE required for GitHub Copilot, or optional?

GitHub's OAuth implementation for Copilot strongly recommends PKCE for public clients and requires it for certain Enterprise configurations. OmniRoute's provider implementation uses PKCE unconditionally to ensure maximum security across all deployment scenarios.

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 →