Documentation Index
Fetch the complete documentation index at: https://mintlify.com/samarth777/claude-code-copilot/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The authentication script implements GitHub’s OAuth device code flow to obtain an access token for the Copilot API. It guides users through browser-based authentication and securely stores credentials.
Command
Authentication flow
The script follows a 5-step OAuth device code flow:
- Initiate device code - Request a user code from GitHub
- Display code - Show the code and verification URL to the user
- Poll for token - Wait for user authorization
- Verify token - Confirm the token works with GitHub API
- Save credentials - Store token to
~/.claude-copilot-auth.json
Functions
initiateDeviceCode()
Initiates the OAuth device code flow with GitHub.
async function initiateDeviceCode() {
const response = await fetch(DEVICE_CODE_URL, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent": USER_AGENT,
},
body: JSON.stringify({
client_id: CLIENT_ID,
scope: "read:user",
}),
})
if (!response.ok) {
throw new Error(
`Failed to initiate device code flow: ${response.status} ${response.statusText}`
)
}
return response.json()
}
Returns: Object containing device_code, user_code, verification_uri, and interval
Error handling: Throws descriptive error if the initial request fails
pollForToken(deviceCode, interval)
Polls GitHub’s token endpoint until the user completes authorization.
Device code received from initiateDeviceCode()
Polling interval in seconds (adds 1 second safety margin)
async function pollForToken(deviceCode, interval) {
const pollInterval = (interval + 1) * 1000 // Add safety margin
while (true) {
await new Promise((resolve) => setTimeout(resolve, pollInterval))
const response = await fetch(ACCESS_TOKEN_URL, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent": USER_AGENT,
},
body: JSON.stringify({
client_id: CLIENT_ID,
device_code: deviceCode,
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
}),
})
const data = await response.json()
if (data.access_token) {
return data.access_token
}
if (data.error === "authorization_pending") {
process.stdout.write(".")
continue
}
if (data.error === "slow_down") {
await new Promise((resolve) => setTimeout(resolve, 5000))
continue
}
if (data.error === "expired_token") {
throw new Error("Device code expired. Please try again.")
}
if (data.error === "access_denied") {
throw new Error("Authorization was denied by user.")
}
throw new Error(`Unexpected error: ${data.error} - ${data.error_description}`)
}
}
Returns: GitHub access token string
Error states:
authorization_pending - User hasn’t authorized yet (continues polling)
slow_down - Rate limit hit (waits 5 seconds)
expired_token - Code expired (throws error)
access_denied - User rejected authorization (throws error)
verifyToken(token)
Verifies the access token works by calling GitHub’s user API.
GitHub access token to verify
async function verifyToken(token) {
const response = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${token}`,
"User-Agent": USER_AGENT,
},
})
if (!response.ok) {
throw new Error("Token verification failed")
}
return response.json()
}
Returns: GitHub user object with login, name, etc.
Error handling: Throws error if token is invalid
checkCopilotAccess(token)
Verifies the token has Copilot API access.
GitHub access token to check
async function checkCopilotAccess(token) {
const response = await fetch("https://api.githubcopilot.com/models", {
headers: {
Authorization: `Bearer ${token}`,
"User-Agent": USER_AGENT,
"Openai-Intent": "conversation-edits",
},
})
return response.ok || response.status === 401
}
Returns: true if access is confirmed or likely valid (401 may indicate different auth format)
Token storage
Credentials are saved to ~/.claude-copilot-auth.json with the following structure:
{
"access_token": "gho_xxxxxxxxxxxxx",
"provider": "github-copilot",
"github_user": "username",
"created_at": "2026-03-03T12:00:00.000Z"
}
The auth file location can be customized via the COPILOT_AUTH_FILE environment variable:
COPILOT_AUTH_FILE=/custom/path/auth.json node scripts/auth.mjs
Configuration
OAuth client ID: Ov23li8tweQw6odWQebz
GitHub device code endpoint: https://github.com/login/device/code
GitHub token endpoint: https://github.com/login/oauth/access_token
Token storage location (default: ~/.claude-copilot-auth.json)
HTTP user agent: claude-code-copilot-provider/1.0.0
User experience
The script provides a guided authentication experience:
- Automatic browser launch - Opens verification URL automatically on macOS, Windows, and Linux
- Visual feedback - Box-formatted user code display
- Progress indicator - Dots printed during polling
- Re-authentication check - Detects existing valid tokens and prevents unnecessary re-auth
Example output
╔══════════════════════════════════════════════════════════╗
║ GitHub Copilot Authentication for Claude Code ║
╚══════════════════════════════════════════════════════════╝
Initiating GitHub OAuth device code flow...
┌──────────────────────────────────────────────────────────┐
│ │
│ Your code: ABCD-1234 │
│ │
│ Open this URL in your browser: │
│ https://github.com/login/device │
│ │
│ Enter the code above and authorize the application. │
│ │
└──────────────────────────────────────────────────────────┘
(Browser opened automatically)
Waiting for authorization......
✓ Authenticated as: username (Display Name)
✓ Token saved to: /home/user/.claude-copilot-auth.json
You can now start the proxy server:
node scripts/proxy.mjs
Then run Claude Code with:
ANTHROPIC_BASE_URL=http://localhost:18080 ANTHROPIC_API_KEY=copilot-proxy claude
Error handling
The script handles various error conditions:
Invalid existing token
if (existsSync(AUTH_FILE)) {
try {
const existing = JSON.parse(readFileSync(AUTH_FILE, "utf-8"))
if (existing.access_token) {
const user = await verifyToken(existing.access_token)
console.log(`Already authenticated as: ${user.login}`)
// ... instructions to re-authenticate
return
}
} catch {
// Token invalid, proceed with new auth
console.log("Existing token is invalid, starting fresh authentication...\n")
}
}
Authentication failure
main().catch((err) => {
console.error("\n✗ Authentication failed:", err.message)
process.exit(1)
})
Next steps
After successful authentication:
- Start the proxy server:
node scripts/proxy.mjs
- Launch Claude Code with the proxy:
ANTHROPIC_BASE_URL=http://localhost:18080 ANTHROPIC_API_KEY=copilot-proxy claude
Re-authentication
To re-authenticate with a different GitHub account:
rm ~/.claude-copilot-auth.json
node scripts/auth.mjs