Skip to content

feat(oauth): GitHub Copilot device-flow login#153

Closed
Wibias wants to merge 4 commits into
lidge-jun:mainfrom
Wibias:feat/github-copilot-oauth
Closed

feat(oauth): GitHub Copilot device-flow login#153
Wibias wants to merge 4 commits into
lidge-jun:mainfrom
Wibias:feat/github-copilot-oauth

Conversation

@Wibias

@Wibias Wibias commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add ocx login github-copilot (GitHub device flow → copilot_internal/v2/token exchange) so Copilot Pro subscriptions work without a pasted API key.
  • Flip the github-copilot registry preset from key → oauth with candid ToS/client-id notes, editor fingerprint headers, and lazy-only refresh.
  • Harden against common review findings: no token leaks in errors, allowlisted github.com/login/device browser opens, allowlisted *.githubcopilot.com API hosts (no projectId overload / SSRF), cancel/slow_down handling.

Closes #151

Notes for reviewers

  • Uses the public VS Code GitHub OAuth client id (Iv1.b507a08c87ecfe98) — unofficial bridge; GitHub may tighten this path.
  • Breaking: pasted Copilot “API keys” via key-login no longer apply for this provider id.
  • React Doctor may stay red until feat(gui): add Frontier benchmark guide page #144 merges (schema pin), unrelated to this change.

Test plan

  • bun test tests/github-copilot-oauth.test.ts tests/provider-registry-parity.test.ts tests/oauth-public-surface.test.ts
  • ocx login github-copilot with an active Copilot Pro account — device code + dashboard login
  • Confirm ~/.opencodex/auth.json stores Copilot access + GitHub refresh (no secrets in CLI output)
  • Route a chat turn through github-copilot / default model and confirm 200
  • Logout / re-login; cancel mid-device-flow

Exchange a GitHub device-flow login for a short-lived Copilot API token via copilot_internal, with allowlisted verify/API URLs, redacted errors, and lazy-only refresh.
@Wibias Wibias changed the title feat(oauth): GitHub Copilot device-flow login (#151) feat(oauth): GitHub Copilot device-flow login Jul 18, 2026
Wibias added 3 commits July 18, 2026 20:31
Avoid email-shaped URL userinfo literals and stop fabricating noreply addresses from GitHub login.
Accept CLI report schemaVersion 3 and grant pull-requests:read so fork PR changed-file listing works.
@Wibias

Wibias commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

I do not have a Copilot account, so its kinda hard to test for me.

lidge-jun pushed a commit that referenced this pull request Jul 19, 2026
Exchange a GitHub device-flow login for a short-lived Copilot API token via copilot_internal, with allowlisted verify/API URLs, redacted errors, and lazy-only refresh.

(cherry picked from commit 9cb236c)

Community PR #153 absorb; source head 1034be9.
lidge-jun pushed a commit that referenced this pull request Jul 19, 2026
Avoid email-shaped URL userinfo literals and stop fabricating noreply addresses from GitHub login.

(cherry picked from commit 77e611c)

Community PR #153 absorb; source head 1034be9.
lidge-jun added a commit that referenced this pull request Jul 19, 2026
…ewal, redaction, identity

Security repairs for community PR #153 absorb (source head 1034be9), Sol
C4 review findings:

- registry: github-copilot preset gains allowKeyAuthOverride so persisted
  authMode:'key' users keep working after the key->oauth flip (router honors
  the override; same pattern as xai).
- device flow: access-token-only success (classic gho_ tokens, no refresh
  token) is now valid; the credential refresh field carries the DURABLE
  GitHub grant (gho_ access token or ghr_ refresh token). def.refresh
  inspects the prefix: ghr_ -> refresh grant + Copilot exchange, otherwise
  direct Copilot re-exchange — expiry renewal and 401 recovery work for both.
- poll cadence: wait-before-poll per RFC 8628, slow_down adds +5s (server
  interval wins), every poll fetch bounded by remaining flow lifetime.
- redaction: GitHub token prefixes (ghp_/gho_/ghu_/ghs_/ghr_/github_pat_),
  the Copilot tid=...;...:sig token grammar, and raw JSON token fields are
  fully redacted; upstream-error path can no longer echo credentials.
- identity: /user lookup retries once then FAILS the login — identity-less
  GitHub credentials are never persisted, so a transient failure cannot
  clobber another account via the active-slot replace path.
- terminal refresh: allowlisted OAuth codes (invalid_grant/access_denied/
  expired_token) surface as status-only messages and now match
  isTerminalRefreshError, marking needsReauth instead of retrying forever.
- 401 replay: the oauth-401 refresh+replay branch now covers github-copilot
  (was reachable only for xai).
- transport: OAuth bearers fail closed to allowlisted *.githubcopilot.com
  hosts even when the credential lacks endpoints.api or baseUrl was edited.
- Activation tests for each repair (access-only login, gho_ re-exchange,
  terminal-code canary leak check, identity fail/retry, host fail-closed,
  token-grammar redaction).

Co-authored-by: Wibias <37517432+Wibias@users.noreply.github.com>
lidge-jun added a commit that referenced this pull request Jul 19, 2026
…oss locales

P3 follow-ups for community PR #153 absorb (source head 1034be9):

- providers.md: preset catalog counts updated to the actual registry
  (53 presets: 42 key, 7 OAuth, 3 local, 1 forward).
- ko/zh-cn provider guides: GitHub Copilot section now describes the
  device-flow OAuth login (ocx login github-copilot) with the unofficial-
  bridge caveat instead of the stale subscription-token guidance.
- Removed the unused assertNoSecretLeak production helper from the oauth
  module (test-only concern living in production code).

Co-authored-by: Wibias <37517432+Wibias@users.noreply.github.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Thanks — this was the biggest community contribution yet, and the device-flow architecture (VS Code client id → copilot_internal exchange, host allowlists, honest editor headers) was solid. It's landed on dev with your authorship preserved plus maintainer security hardening on top:

  • 8af3166a / e3e11b56 — your PR feat(oauth): GitHub Copilot device-flow login #153 feature + privacy-fixture commits, absorbed as-is (author: @Wibias, source head 1034be9).
  • 70483eef — maintainer security repairs (Co-authored-by: @Wibias) closing the C4 review findings:
    1. the registry preset flip (key→oauth) silently broke persisted authMode:"key" users — allowKeyAuthOverride added (same pattern as xai);
    2. access-token-only device-flow success (classic gho_ tokens, no refresh token) was rejected — the credential refresh field now carries the durable GitHub grant (gho_ or ghr_), and refresh inspects the prefix so expiry renewal and 401 recovery work for both shapes;
    3. the Copilot tid=…;… token grammar and GitHub token prefixes weren't fully redacted on the upstream-error path — redaction extended and leak-tested with canaries;
    4. a transient /user failure produced an identity-less credential that could clobber another account — identity is now required (one retry, then the login fails cleanly);
    5. RFC 8628 cadence (wait-before-poll, slow_down +5s, lifetime-bounded fetches);
    6. the oauth-401 refresh+replay branch was xAI-only — now covers github-copilot;
    7. terminal refresh codes (invalid_grant/access_denied/expired_token) surface status-only and mark needsReauth;
    8. transport fails closed to allowlisted *.githubcopilot.com hosts even without endpoints.api.
  • 90d9a188 — docs follow-ups (preset counts, ko/zh guides).

Full suite green (3,087 tests) + privacy scan. Closing in favor of the dev-landed commits; ships with the next release. Closes #151.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: auth login for GitHub Copilot

2 participants