|
@@ -1,147 +0,0 @@
|
|
|
-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": "GitHubCopilotChat/0.26.7",
|
|
|
|
|
- },
|
|
|
|
|
- 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": "GitHubCopilotChat/0.26.7",
|
|
|
|
|
- },
|
|
|
|
|
- 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": "GitHubCopilotChat/0.26.7",
|
|
|
|
|
- "Editor-Version": "vscode/1.99.3",
|
|
|
|
|
- "Editor-Plugin-Version": "copilot-chat/0.26.7",
|
|
|
|
|
- },
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- 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(),
|
|
|
|
|
- }),
|
|
|
|
|
- )
|
|
|
|
|
-}
|
|
|