How Headroom Handles GitHub Copilot CLI Subscription Authentication
Headroom authenticates the GitHub Copilot subscription flow by discovering a reusable GitHub OAuth token, optionally exchanging it for a short-lived Copilot API token, and then injecting that token into every request that targets the Copilot endpoint.
The chopratejas/headroom project implements a robust authentication pipeline for GitHub Copilot CLI subscription mode through its core authentication module. This system prioritizes token security by validating credentials against GitHub's Copilot user-info endpoint before allowing API access.
Token Discovery and OAuth Resolution
Headroom implements a cascading token discovery system in headroom/copilot_auth.py that examines multiple credential sources in priority order.
Environment Variable Shortcuts
The authentication process begins with resolve_client_bearer_token, which checks for explicitly configured API tokens first. The function scans for GITHUB_COPILOT_API_TOKEN followed by generic GitHub token variables including GH_TOKEN and GITHUB_TOKEN.
If a direct API token is not found in the environment, Headroom falls back to an OAuth-style discovery mechanism through iter_oauth_token_candidates. This function searches:
- Environment variables (
GITHUB_COPILOT_GITHUB_TOKEN,GITHUB_COPILOT_TOKEN) - Platform-specific credential stores (Windows Credential Manager, macOS Keychain, Linux Secret Service)
- Copilot credential files located at
~/.config/github-copilot/*.json - GitHub CLI authentication via
gh auth token
The discovery logic prioritizes the safest token locations first, ensuring that system keychains are preferred over plaintext files when available.
Subscription-Specific Validation
Once candidate tokens are identified, resolve_subscription_bearer_token validates each credential against the Copilot user-info endpoint (/copilot_internal/user). This verification step ensures that only tokens with active Copilot subscriptions are accepted. The first token that receives a successful response from the GitHub API becomes the subscription bearer token used for subsequent requests.
Optional Token Exchange Mechanism
Headroom supports an advanced token exchange workflow governed by the GITHUB_COPILOT_USE_TOKEN_EXCHANGE environment variable. When this flag is set to a truthy value, the system calls _should_exchange_oauth_token to trigger the exchange process.
The CopilotTokenProvider._exchange_token_sync method makes a GET request to https://api.github.com/copilot_internal/v2/token, exchanging the long-lived OAuth token for a short-lived Copilot API token. This exchange returns an explicit API endpoint, the temporary token, and expiry information that the provider uses for automatic rotation.
Request Header Injection
All outbound HTTP requests pass through apply_copilot_api_auth before reaching the Copilot API. This function performs three critical operations:
- Checks
is_copilot_api_urlto confirm the request targetsapi.githubcopilot.com - Retrieves a fresh token from the shared
CopilotTokenProviderviaget_api_token - Replaces any existing
Authorizationheader withBearer <token>
This interception ensures that every proxied request carries valid authentication credentials without requiring manual header management from the user.
End-to-End Authentication Flow
When a user executes the subscription mode wrapper:
headroom wrap copilot --subscription -- --model gpt-4o
The system instantiates a local proxy that manages authentication automatically. On the first request to the Copilot API, apply_copilot_api_auth triggers the resolution pipeline. An OAuth token is discovered and validated, optionally exchanged for a short-lived token, and cached in CopilotTokenProvider._cached for the lifetime of the proxy process (defaulting to one hour). Subsequent requests reuse the cached token until expiration, at which point the provider automatically fetches fresh credentials.
Practical Implementation Examples
Obtaining the Subscription Token in Python
from headroom import copilot_auth
# Resolve the token that the Copilot subscription API will accept
subscription_token = copilot_auth.resolve_subscription_bearer_token()
print("Subscription token:", subscription_token)
This calls the same discovery and validation logic that the CLI wrapper uses internally.
Using the Token Provider Directly
import asyncio
from headroom.copilot_auth import get_copilot_token_provider
async def fetch_token():
provider = get_copilot_token_provider()
token = await provider.get_api_token()
print("API token:", token.token)
print("Expires at:", token.expires_at)
asyncio.run(fetch_token())
The provider automatically handles OAuth token exchange based on the GITHUB_COPILOT_USE_TOKEN_EXCHANGE environment variable.
Configuring the Environment
# Export a generic GitHub token as fallback
export GH_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXX
# Enable token exchange for short-lived tokens (optional)
export GITHUB_COPILOT_USE_TOKEN_EXCHANGE=true
# Run the proxy with automatic authentication injection
headroom wrap copilot --subscription -- --model gpt-4o
Summary
- Multi-source token discovery in
headroom/copilot_auth.pychecks environment variables, system keychains, and credential files to locate valid OAuth tokens. - Subscription validation occurs against the
/copilot_internal/userendpoint to ensure tokens have active Copilot access before use. - Optional token exchange converts long-lived OAuth tokens into short-lived API tokens when
GITHUB_COPILOT_USE_TOKEN_EXCHANGEis enabled. - Automatic header injection via
apply_copilot_api_authensures all proxied requests toapi.githubcopilot.cominclude validBearertokens. - In-memory caching in
CopilotTokenProvider._cachedminimizes authentication overhead while respecting token expiration times.
Frequently Asked Questions
What environment variables does Headroom check for GitHub Copilot authentication?
Headroom checks GITHUB_COPILOT_API_TOKEN first, then falls back to generic GitHub tokens (GH_TOKEN, GITHUB_TOKEN). For OAuth-style discovery, it examines GITHUB_COPILOT_GITHUB_TOKEN and GITHUB_COPILOT_TOKEN before querying system credential stores and the GitHub CLI.
How does Headroom validate OAuth tokens for subscription mode?
The resolve_subscription_bearer_token function iterates over discovered token candidates and validates each against the GitHub Copilot user-info endpoint (/copilot_internal/user). Only tokens that return successful responses—indicating active Copilot subscriptions—are accepted for API requests.
What is the purpose of the token exchange mechanism in Headroom?
When GITHUB_COPILOT_USE_TOKEN_EXCHANGE is set to true, Headroom exchanges long-lived OAuth tokens for short-lived Copilot API tokens via the /copilot_internal/v2/token endpoint. This improves security by reducing the exposure window of credentials and provides explicit expiration metadata for automatic rotation.
How long are tokens cached when using Headroom's Copilot wrapper?
Tokens are cached in CopilotTokenProvider._cached for the duration of the proxy process, defaulting to one hour or until the token's expiration time—whichever comes first. The provider automatically refreshes the token when it expires or when explicitly invalidated.
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 →