Skip to main content

Overview

Claude Code Copilot uses GitHub’s OAuth device code flow to authenticate with your GitHub Copilot subscription. This is the same authentication method used by VS Code and other official GitHub tools.
No Anthropic API key required — The authentication process only connects to GitHub. Your Copilot subscription provides access to Claude models.

Authentication flow

The authentication process follows GitHub’s secure device code flow:
1

Initiate device code flow

The auth script requests a device code from GitHub’s OAuth server:
scripts/auth.mjs
const CLIENT_ID = "Ov23li8tweQw6odWQebz"
const DEVICE_CODE_URL = "https://github.com/login/device/code"

const response = await fetch(DEVICE_CODE_URL, {
  method: "POST",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    client_id: CLIENT_ID,
    scope: "read:user"
  })
})
2

Display user code

You’ll see a unique code in your terminal:
┌──────────────────────────────────────────────────────────┐
│                                                          │
│   Your code:  XXXX-XXXX                                  │
│                                                          │
│   Open this URL in your browser:                         │
│   https://github.com/login/device                        │
│                                                          │
│   Enter the code above and authorize the application.    │
│                                                          │
└──────────────────────────────────────────────────────────┘
The browser opens automatically on macOS, Windows, and Linux.
3

Authorize in browser

In your browser:
  1. Enter the displayed code
  2. Review the requested permissions (read:user)
  3. Click “Authorize” to grant access
4

Poll for access token

The script polls GitHub’s token endpoint until you complete authorization:
scripts/auth.mjs
async function pollForToken(deviceCode, interval) {
  const pollInterval = (interval + 1) * 1000

  while (true) {
    await new Promise((resolve) => setTimeout(resolve, pollInterval))

    const response = await fetch(ACCESS_TOKEN_URL, {
      method: "POST",
      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
    }
  }
}
5

Save credentials

Once authorized, your token is saved to ~/.claude-copilot-auth.json:
~/.claude-copilot-auth.json
{
  "access_token": "gho_xxxxxxxxxxxxxxxxxxxx",
  "provider": "github-copilot",
  "github_user": "your-username",
  "created_at": "2026-03-03T12:00:00.000Z"
}

Running authentication

Authenticate with GitHub by running the auth script:
node scripts/auth.mjs
Or using npm:
npm run auth
The authentication script will automatically open your default browser. If it doesn’t, manually navigate to the URL shown in the terminal.

Credential storage

Authentication credentials are stored locally in a JSON file: Default location:
~/.claude-copilot-auth.json
Custom location: Set the COPILOT_AUTH_FILE environment variable:
export COPILOT_AUTH_FILE="/path/to/custom/auth.json"
node scripts/auth.mjs
Keep your auth file secure! It contains your GitHub access token. Never commit it to version control or share it publicly.

Token verification

The auth script verifies your token by checking:
  1. GitHub API access:
    scripts/auth.mjs
    async function verifyToken(token) {
      const response = await fetch("https://api.github.com/user", {
        headers: {
          Authorization: `Bearer ${token}`,
          "User-Agent": "claude-code-copilot-provider/1.0.0"
        }
      })
    
      if (!response.ok) {
        throw new Error("Token verification failed")
      }
    
      return response.json()
    }
    
  2. Copilot API access:
    scripts/auth.mjs
    async function checkCopilotAccess(token) {
      const response = await fetch("https://api.githubcopilot.com/models", {
        headers: {
          Authorization: `Bearer ${token}`,
          "Openai-Intent": "conversation-edits"
        }
      })
    
      return response.ok || response.status === 401
    }
    

Re-authentication

If you need to re-authenticate (e.g., token expired or revoked):
1

Remove existing credentials

Delete the stored authentication file:
rm ~/.claude-copilot-auth.json
2

Run auth script again

Authenticate with fresh credentials:
node scripts/auth.mjs
The auth script automatically detects existing credentials. If valid, it will skip re-authentication and display your current GitHub username.

Troubleshooting

Your token may have expired or been revoked. Re-authenticate:
rm ~/.claude-copilot-auth.json
node scripts/auth.mjs
If you don’t authorize within the time limit (usually 15 minutes), the device code expires:
✗ Authentication failed: Device code expired. Please try again.
Simply run the auth script again to get a new code.
If you click “Cancel” during authorization:
✗ Authentication failed: Authorization was denied by user.
Run the auth script again and complete the authorization.
Ensure you have an active GitHub Copilot subscription:
  1. Go to github.com/settings/copilot
  2. Verify your subscription status
  3. Purchase or enable Copilot if needed
If the browser doesn’t open:
  1. Copy the URL from the terminal output
  2. Manually open it in your browser
  3. Enter the displayed code

Security considerations

Token scope

The auth flow only requests read:user scope — the minimum needed to identify your account

Local storage

Credentials are stored locally on your machine, never sent to third parties

No data logging

The proxy doesn’t log or store any request data or API responses

Revocation

Revoke access anytime at github.com/settings/applications

Next steps

Docker setup

Deploy the proxy as a persistent Docker container with automatic restarts