GitHub Copilot Authentication Flow | Generated by AI
Good question — GitHub Copilot’s authentication flow is basically a standard OAuth2 device code grant, but with some GitHub-specific tokens layered on top for the Copilot service itself. Let me break it down step by step:
1. Device Flow (/login/device/code
)
-
When you first log in, the Copilot client (e.g., VS Code extension, JetBrains plugin, or CLI) calls GitHub’s OAuth endpoint:
POST https://github.com/login/device/code
- It sends along the client_id (specific to GitHub Copilot).
-
GitHub responds with:
device_code
(internal code used for polling),user_code
(the one you see and enter in your browser),verification_uri
(the URL you visit to enter the code),interval
(how often the client should poll).
2. Polling for Access Token
-
The Copilot client then polls:
POST https://github.com/login/oauth/access_token
- It includes the
device_code
andclient_id
. -
Once you’ve approved in your browser, GitHub returns:
access_token
(a GitHub OAuth token scoped for Copilot usage),token_type=bearer
,expires_in
(lifetime).
This access_token
is a normal GitHub OAuth2 token.
3. Exchanging for copilot_internal
Token
- The Copilot client cannot call Copilot APIs directly with the GitHub OAuth token.
-
Instead, it exchanges it with the Copilot service:
POST https://api.github.com/copilot_internal/v2/token Authorization: Bearer <GitHub OAuth access_token>
-
The response is:
{ "token": "<copilot_internal token>", "expires_at": "...", "user": { ... } }
- This
copilot_internal
v2 token is what the Copilot client uses to talk to the Copilot inference service (e.g.,https://copilot-proxy.githubusercontent.com
).
4. Using the copilot_internal
Token
-
All subsequent completions or chat requests are authenticated with:
Authorization: Bearer <copilot_internal token>
- This token has a short lifetime (usually ~1 hour) and is tied to your GitHub account + Copilot subscription status.
- The client refreshes it periodically by re-exchanging the GitHub OAuth access token.
✅ In summary:
/login/device/code
→ gives you a code to authenticate in browser./login/oauth/access_token
→ gives you a GitHub OAuth token./copilot_internal/v2/token
→ exchanges that for a short-lived Copilot token, which is the real credential used for completions.
Would you like me to also draw the exact request/response examples (with headers and sample JSON) so you can see what the payloads look like in practice?