Skip to main content

GitHub OAuth 设置

让用户使用其GitHub帐户进行身份验证,以便通过应用程序使用Copilot。 这支持个人帐户、组织成员身份和企业标识。

最适合: 多用户应用、具有组织级访问控制的内部工具、SaaS 产品、用户拥有 GitHub 账户的应用。

工作原理

创建GitHub OAuth 应用(或GitHub应用),用户对其进行授权,并将其访问令牌传递给 SDK。 Copilot 请求会代表每位经过身份验证的用户发出,并使用其 Copilot 订阅。

关系图:显示描述的过程的序列图。

主要特征:

  • 每个用户使用自己的GitHub帐户进行身份验证
  • Copilot 使用费用将计入每个用户的订阅
  • 支持GitHub组织和企业帐户
  • 你的应用永远不会处理模型 API 密钥 - GitHub管理所有内容

Architecture

图示:显示所述流程的流程图。

步骤 1:创建GitHub OAuth 应用

  1. 转到GitHub设置→开发人员设置→ OAuth 应用→新 OAuth 应用(或适用于组织:组织设置→开发人员设置

  2. 填写:

    • 应用程序名称:应用的名称
    • 主页 URL:应用的 URL
    • 授权回调 URL:您的 OAuth 回调端点(例如 https://yourapp.com/auth/callback
  3. 记下 客户端 ID 并生成 客户端密码

GitHub 应用与 OAuth 应用: 两者都可以。 GitHub应用提供精细的权限,建议用于新项目。 OAuth 应用设置更简单。 从 SDK 的角度来看,令牌流是相同的。

步骤 2:实现 OAuth 流

应用程序处理标准GitHub OAuth 流。 下面是服务器端令牌交换:

// Server-side: Exchange authorization code for user token
async function handleOAuthCallback(code: string): Promise<string> {
    const response = await fetch("https://github.com/login/oauth/access_token", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
        },
        body: JSON.stringify({
            client_id: process.env.GITHUB_CLIENT_ID,
            client_secret: process.env.GITHUB_CLIENT_SECRET,
            code,
        }),
    });

    const data = await response.json();
    return data.access_token; // gho_xxxx or ghu_xxxx
}

步骤 3:将令牌传递给 SDK

为每个经过身份验证的用户创建 SDK 客户端,并传递其令牌:

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

// Create a client for an authenticated user
function createClientForUser(userToken: string): CopilotClient {
    return new CopilotClient({
        gitHubToken: userToken,
        useLoggedInUser: false,  // Don't fall back to CLI login
    });
}

// Usage
const client = createClientForUser("gho_user_access_token");
const session = await client.createSession({
    sessionId: `user-${userId}-session`,
    model: "gpt-4.1",
});

const response = await session.sendAndWait({ prompt: "Hello!" });
Python
from copilot import CopilotClient
from copilot.session import PermissionHandler

def create_client_for_user(user_token: str) -> CopilotClient:
    return CopilotClient({
        "github_token": user_token,
        "use_logged_in_user": False,
    })

# Usage
client = create_client_for_user("gho_user_access_token")
await client.start()

session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", session_id=f"user-{user_id}-session")

response = await session.send_and_wait("Hello!")
Go
package main

import (
    "context"
    "fmt"
    copilot "github.com/github/copilot-sdk/go"
)

func createClientForUser(userToken string) *copilot.Client {
    return copilot.NewClient(&copilot.ClientOptions{
        GitHubToken:     userToken,
        UseLoggedInUser: copilot.Bool(false),
    })
}

func main() {
    ctx := context.Background()
    userID := "user1"

    client := createClientForUser("gho_user_access_token")
    client.Start(ctx)
    defer client.Stop()

    session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
        SessionID: fmt.Sprintf("user-%s-session", userID),
        Model:     "gpt-4.1",
    })
    response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"})
    _ = response
}
func createClientForUser(userToken string) *copilot.Client {
    return copilot.NewClient(&copilot.ClientOptions{
        GithubToken:     userToken,
        UseLoggedInUser: copilot.Bool(false),
    })
}

// Usage
client := createClientForUser("gho_user_access_token")
client.Start(ctx)
defer client.Stop()

session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID: fmt.Sprintf("user-%s-session", userID),
    Model:     "gpt-4.1",
})
response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"})
.NET
using GitHub.Copilot;

CopilotClient CreateClientForUser(string userToken) =>
    new CopilotClient(new CopilotClientOptions
    {
        GitHubToken = userToken,
        UseLoggedInUser = false,
    });

var userId = "user1";

await using var client = CreateClientForUser("gho_user_access_token");
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{userId}-session",
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = "Hello!" });
CopilotClient CreateClientForUser(string userToken) =>
    new CopilotClient(new CopilotClientOptions
    {
        GitHubToken = userToken,
        UseLoggedInUser = false,
    });

// Usage
await using var client = CreateClientForUser("gho_user_access_token");
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = $"user-{userId}-session",
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = "Hello!" });
Java
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

CopilotClient createClientForUser(String userToken) throws Exception {
    var client = new CopilotClient(new CopilotClientOptions()
        .setGitHubToken(userToken)
        .setUseLoggedInUser(false)
    );
    client.start().get();
    return client;
}

// Usage — use try-with-resources to ensure cleanup
var userId = "user1";
try (var client = createClientForUser("gho_user_access_token")) {
    var session = client.createSession(new SessionConfig()
        .setSessionId(String.format("user-%s-session", userId))
        .setModel("gpt-4.1")
        .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    var response = session.sendAndWait(new MessageOptions()
        .setPrompt("Hello!")).get();
}

企业和组织访问权限

GitHub OAuth 自然支持企业方案。 当用户使用GitHub进行身份验证时,其组织成员资格和企业关联也随之而来。

图示:显示所述过程的流程图。

验证组织成员身份

OAuth 后,检查用户是否属于组织:

async function verifyOrgMembership(
    token: string,
    requiredOrg: string
): Promise<boolean> {
    const response = await fetch("https://api.github.com/user/orgs", {
        headers: { Authorization: `Bearer ${token}` },
    });
    const orgs = await response.json();
    return orgs.some((org: any) => org.login === requiredOrg);
}

// In your auth flow
const token = await handleOAuthCallback(code);
if (!await verifyOrgMembership(token, "my-company")) {
    throw new Error("User is not a member of the required organization");
}
const client = createClientForUser(token);

企业托管用户(EMU)

对于GitHub企业托管用户,流是相同的 — EMU 用户像任何其他用户一样通过 GitHub OAuth 进行身份验证。 其企业策略(IP 限制、SAML SSO)由 GitHub 自动强制执行。

// No special SDK configuration needed for EMU
// Enterprise policies are enforced server-side by GitHub
const client = new CopilotClient({
    gitHubToken: emuUserToken,  // Works the same as regular tokens
    useLoggedInUser: false,
});

支持的令牌类型

令牌前缀来源可以用吗?
gho_OAuth 用户访问令牌
ghu_GitHub应用用户访问令牌
github_pat_细粒度的个人访问令牌
ghp_经典个人访问令牌
❌(已弃用)

令牌生命周期

图示:显示所述过程的流程图。

重要: 应用程序负责令牌存储、刷新和过期处理。 SDK 使用你提供的任何令牌 -- 它不管理 OAuth 生命周期。

令牌刷新模式

async function getOrRefreshToken(userId: string): Promise<string> {
    const stored = await tokenStore.get(userId);

    if (stored && !isExpired(stored)) {
        return stored.accessToken;
    }

    if (stored?.refreshToken) {
        const refreshed = await refreshGitHubToken(stored.refreshToken);
        await tokenStore.set(userId, refreshed);
        return refreshed.accessToken;
    }

    throw new Error("User must re-authenticate");
}

多用户模式

每个用户使用自己的令牌获取自己的 SDK 客户端。 这提供最强的隔离。

const clients = new Map<string, CopilotClient>();

function getClientForUser(userId: string, token: string): CopilotClient {
    if (!clients.has(userId)) {
        clients.set(userId, new CopilotClient({
            gitHubToken: token,
            useLoggedInUser: false,
        }));
    }
    return clients.get(userId)!;
}

使用按请求分配令牌的共享 CLI

对于较轻的资源占用情况,可以运行单个外部 CLI 服务器并为每个会话传递令牌。 有关此模式,请参阅 后端服务设置

局限性

Limitation详细信息
需要 Copilot 订阅每个用户都需要一个有效的 Copilot 订阅
令牌管理是你的责任存储、刷新和处理过期
需要GitHub帐户用户必须具有GitHub帐户
每个用户的速率限制取决于各用户的 Copilot 速率限制

何时继续

需要下一篇指南
没有GitHub帐户的用户
BYOK (bring your own key)
在服务器上运行 SDK
后端服务设置
处理多个并发用户
可扩展性和多租户

后续步骤