GitHub OAuth Device Code Flow | Generated by AI

Home 2025.10

Overview

This JavaScript code implements the OAuth 2.0 Device Authorization Grant flow (also known as the Device Code grant) to authenticate with GitHub and obtain an access token. The flow is typically used for headless applications (e.g., CLI tools or embedded systems) where the user can’t interact directly with a web browser to approve the authentication.

In this specific case, it appears to be mimicking requests from the GitHub Copilot plugin (e.g., for Neovim or Vim), using headers that spoof a Copilot client to potentially integrate with or access GitHub’s authentication system. The goal is to generate an access token that could be used for GitHub API calls requiring user authentication, such as reading user info (per the scope: "read:user").

The code runs as a Node.js script, using fetch for HTTP requests and process for environment variables. It assumes Node.js has fetch available (as in newer versions or via a polyfill). If successful, it polls GitHub’s servers until the user authorizes the request or it times out.

Important Notes:

Step-by-Step Breakdown

1. Environment Check

const clientId = process.env.MY_COPILOT_CLIENT_ID;

if (!clientId) {
  console.error("MY_COPILOT_CLIENT_ID is not set");
  process.exit(1);
}

2. Common Headers Setup

const commonHeaders = new Headers();
commonHeaders.append("accept", "application/json");
commonHeaders.append("editor-version", "Neovim/0.6.1");
commonHeaders.append("editor-plugin-version", "copilot.vim/1.16.0");
commonHeaders.append("content-type", "application/json");
commonHeaders.append("user-agent", "GithubCopilot/1.155.0");
commonHeaders.append("accept-encoding", "gzip,deflate,b");

3. getDeviceCode() Function

async function getDeviceCode() {
  const raw = JSON.stringify({
    "client_id": clientId,
    "scope": "read:user",
  });

  const requestOptions = {
    method: "POST",
    headers: commonHeaders,
    body: raw,
  };

  const data = await fetch(
    "https://github.com/login/device/code",
    requestOptions,
  )
    .then((response) => response.json())
    .catch((error) => console.error(error));
  return data;
}

4. getAccessToken(deviceCode: string) Function

async function getAccessToken(deviceCode: string) {
  const raw = JSON.stringify({
    "client_id": clientId,
    "device_code": deviceCode,
    "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
  });

  const requestOptions = {
    method: "POST",
    headers: commonHeaders,
    body: raw,
  };

  return await fetch(
    "https://github.com/login/oauth/access_token",
    requestOptions,
  )
    .then((response) => response.json())
    .catch((error) => console.error(error));
}

5. Main Execution (Immediately Invoked Async Function)

(async function () {
  const { device_code, user_code, verification_uri, expires_in } =
    await getDeviceCode();
  console.info(`enter user code:\n${user_code}\n${verification_uri}`);
  console.info(`Expires in ${expires_in} seconds`);
  while (true) {
    await new Promise((resolve) => setTimeout(resolve, 5000));
    const accessToken = await getAccessToken(device_code);
    if (accessToken.error) {
      console.info(`${accessToken.error}: ${accessToken.error_description}`);
    }
    if (accessToken.access_token) {
      console.info(`access token:\n${JSON.stringify(accessToken, null, 1)}`);
      break;
    }
  }
})();

How It Works End-to-End

  1. Step 1: Request Device Code → Script gets a temporary code from GitHub.
  2. Step 2: User Authorization → User visits GitHub and enters the code to grant permission.
  3. Step 3: Poll for Token → Script keeps asking GitHub until the token is issued.
  4. Result: An access token for the specified scope (e.g., read user data via GitHub API).

This is a simulation of how tools like GitHub CLI might work, adapted for Copilot. For official GitHub OAuth docs, refer to https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps#device-flow. If you’re building something similar, ensure compliance with OAuth standards and GitHub’s policies. If you have questions about modifying or running this, let me know!


Back

x-ai/grok-code-fast-1

Donate