| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { z } from "zod"
- import { Auth } from "./index"
- import { NamedError } from "../util/error"
- export namespace AuthGithubCopilot {
- const CLIENT_ID = "Iv1.b507a08c87ecfe98"
- const DEVICE_CODE_URL = "https://github.com/login/device/code"
- const ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token"
- const COPILOT_API_KEY_URL = "https://api.github.com/copilot_internal/v2/token"
- interface DeviceCodeResponse {
- device_code: string
- user_code: string
- verification_uri: string
- expires_in: number
- interval: number
- }
- interface AccessTokenResponse {
- access_token?: string
- error?: string
- error_description?: string
- }
- interface CopilotTokenResponse {
- token: string
- expires_at: number
- refresh_in: number
- endpoints: {
- api: string
- }
- }
- export async function authorize() {
- const deviceResponse = await fetch(DEVICE_CODE_URL, {
- method: "POST",
- headers: {
- Accept: "application/json",
- "Content-Type": "application/json",
- "User-Agent": "GithubCopilot/1.155.0",
- },
- body: JSON.stringify({
- client_id: CLIENT_ID,
- scope: "read:user",
- }),
- })
- const deviceData: DeviceCodeResponse = await deviceResponse.json()
- return {
- device: deviceData.device_code,
- user: deviceData.user_code,
- verification: deviceData.verification_uri,
- interval: deviceData.interval || 5,
- expiry: deviceData.expires_in,
- }
- }
- export async function poll(device_code: string) {
- const response = await fetch(ACCESS_TOKEN_URL, {
- method: "POST",
- headers: {
- Accept: "application/json",
- "Content-Type": "application/json",
- "User-Agent": "GithubCopilot/1.155.0",
- },
- body: JSON.stringify({
- client_id: CLIENT_ID,
- device_code,
- grant_type: "urn:ietf:params:oauth:grant-type:device_code",
- }),
- })
- if (!response.ok) return "failed"
- const data: AccessTokenResponse = await response.json()
- if (data.access_token) {
- // Store the GitHub OAuth token
- await Auth.set("github-copilot", {
- type: "oauth",
- refresh: data.access_token,
- access: "",
- expires: 0,
- })
- return "complete"
- }
- if (data.error === "authorization_pending") return "pending"
- if (data.error) return "failed"
- return "pending"
- }
- export async function access() {
- const info = await Auth.get("github-copilot")
- if (!info || info.type !== "oauth") return
- if (info.access && info.expires > Date.now()) return info.access
- // Get new Copilot API token
- const response = await fetch(COPILOT_API_KEY_URL, {
- headers: {
- Accept: "application/json",
- Authorization: `Bearer ${info.refresh}`,
- "User-Agent": "GithubCopilot/1.155.0",
- "Editor-Version": "vscode/1.85.1",
- "Editor-Plugin-Version": "copilot/1.155.0",
- },
- })
- if (!response.ok) return
- const tokenData: CopilotTokenResponse = await response.json()
- // Store the Copilot API token
- await Auth.set("github-copilot", {
- type: "oauth",
- refresh: info.refresh,
- access: tokenData.token,
- expires: tokenData.expires_at * 1000,
- })
- return tokenData.token
- }
- export const DeviceCodeError = NamedError.create(
- "DeviceCodeError",
- z.object({}),
- )
- export const TokenExchangeError = NamedError.create(
- "TokenExchangeError",
- z.object({
- message: z.string(),
- }),
- )
- export const AuthenticationError = NamedError.create(
- "AuthenticationError",
- z.object({
- message: z.string(),
- }),
- )
- export const CopilotTokenError = NamedError.create(
- "CopilotTokenError",
- z.object({
- message: z.string(),
- }),
- )
- }
|