Skip to content

fix(copilot): add token exchange and editor headers for corporate network compatibility#18782

Open
ykbytes wants to merge 1 commit intoanomalyco:devfrom
ykbytes:fix/copilot-token-exchange
Open

fix(copilot): add token exchange and editor headers for corporate network compatibility#18782
ykbytes wants to merge 1 commit intoanomalyco:devfrom
ykbytes:fix/copilot-token-exchange

Conversation

@ykbytes
Copy link
Copy Markdown

@ykbytes ykbytes commented Mar 23, 2026

Issue for this PR

Closes #18785

Related: #14189 (similar token exchange fix for GitHub Enterprise auth)

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The Copilot plugin sends the raw GitHub OAuth token directly to api.githubcopilot.com. On corporate networks with SSL inspection, this causes requests to hang forever with no error.

I debugged this by comparing what VS Code and Zed do vs what OpenCode does. The difference: VS Code and Zed perform a token exchange before calling the Copilot API. OpenCode skips it entirely.

The flow VS Code uses:

  1. GitHub OAuth device flow -> get access_token (OpenCode already does this)
  2. GET api.github.com/copilot_internal/v2/token with the OAuth token -> get a short-lived Copilot session JWT + the correct API endpoint
  3. Use the session JWT to call the resolved endpoint (e.g. api.individual.githubcopilot.com)

OpenCode was skipping step 2 and sending the raw OAuth token to api.githubcopilot.com (the generic endpoint from models.dev, not the user-specific one returned by the token exchange).

This PR adds to packages/opencode/src/plugin/copilot.ts:

  • Token exchange via copilot_internal/v2/token with caching and TTL-based expiry
  • Dynamic API endpoint resolution from the token exchange response
  • Editor identification headers (Editor-Version, Editor-Plugin-Version, Copilot-Integration-Id)
  • Graceful fallback to the raw OAuth token if the exchange fails, so existing environments where the raw token works are unaffected

How did you verify your code works?

  1. On the affected corporate network, confirmed VS Code Copilot works but OpenCode hangs
  2. Manually called the token exchange endpoint with PowerShell - confirmed it returns a session JWT and the correct endpoint (api.individual.githubcopilot.com)
  3. Made a direct API call using the session JWT + editor headers with PowerShell - got a response in 1.2 seconds
  4. Ran the patched source with bun run dev run 'say hi in 3 words' - got a successful response from gpt-4.1
  5. Verified on a non-corporate network that the fallback path (if token exchange fails) still works

Screenshots / recordings

N/A - not a UI change

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions bot added needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search results, I found one potentially related PR:

PR #14189: "fix(opencode): exchange OAuth token for Copilot JWT to fix GitHub Enterprise auth"
#14189

This PR appears to address a similar issue - exchanging OAuth tokens for Copilot JWT. This could be related to your current PR's token exchange feature, though it was specifically for GitHub Enterprise auth. You should check if this PR was merged or closed, and whether it covers the corporate network SSL inspection scenario or if your PR extends/improves upon that work.

…ate network compatibility

The GitHub Copilot provider was sending the raw GitHub OAuth access token
directly to api.githubcopilot.com. This works in some environments but
fails on corporate networks with SSL inspection (e.g., Zscaler), causing
requests to hang indefinitely with no error.

VS Code, Zed, and other editors that work correctly on these networks
perform a token exchange step first:

1. POST api.github.com/copilot_internal/v2/token with the OAuth token
2. Receive a short-lived Copilot session JWT + the correct API endpoint
3. Use the session JWT and resolved endpoint for API calls

This commit adds:
- Token exchange via copilot_internal/v2/token (with caching + TTL)
- Dynamic API endpoint resolution from the token response
  (e.g., api.individual.githubcopilot.com vs api.githubcopilot.com)
- Editor identification headers (Editor-Version, Editor-Plugin-Version,
  Copilot-Integration-Id) matching the expected format
- VS Code OAuth Client ID (Iv1.b507a08c87ecfe98)
- Graceful fallback to the raw OAuth token if exchange fails

Fixes GitHub Copilot hanging on corporate networks with SSL inspection.
@ykbytes ykbytes force-pushed the fix/copilot-token-exchange branch from 970301d to f2b5e2a Compare March 23, 2026 12:36
@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitHub Copilot hangs indefinitely on corporate networks with SSL inspection

1 participant