# Authentication

GitHub Copilot SDK 支持多种身份验证方法以适应不同的用例。 选择最适合部署方案的方法。

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## 身份验证方法

| 方法                                                                          | 用例                                       | 需要Copilot订阅  |
| --------------------------------------------------------------------------- | ---------------------------------------- | ------------ |
| [GitHub已登录用户](#github-signed-in-user)                                       | 用户使用GitHub登录的交互式应用                       | 是            |
| [GitHub OAuth 应用](#github-oauth-app)                                        | 通过 OAuth 代表用户运行的应用                       | 是            |
| [环境变量](#environment-variables)                                              | CI/CD、自动化、服务器到服务器                        | 是            |
| [服务器到服务器身份验证](/zh/copilot/how-tos/copilot-sdk/auth/server-to-server-tokens) | 归属于组织的自动化和直接向组织计费                        | 无用户订阅;需要组织策略 |
| [BYOK （自带密钥）](/zh/copilot/how-tos/copilot-sdk/auth/byok)                    | 使用自己的 API 密钥（Microsoft Foundry、OpenAI 等） | 否            |

## GitHub 登录用户

这是以交互方式运行 Copilot CLI 时的默认身份验证方法。 用户通过 GitHub OAuth 设备流进行身份验证，SDK 使用其存储的凭据。

**工作原理**：

1. 用户运行 `copilot` CLI 并通过 GitHub OAuth 登录
2. 凭据安全地存储在系统密钥链中
3. SDK 自动使用存储的凭据

**SDK 配置：**

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
using GitHub.Copilot;

// Default: uses logged-in user credentials
await using CopilotClient client = new();
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
import copilot "github.com/github/copilot-sdk/go"

// Default: uses logged-in user credentials
client := copilot.NewClient(nil)
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
import com.github.copilot.CopilotClient;

// Default: uses logged-in user credentials
var client = new CopilotClient();
client.start().get();
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from copilot import CopilotClient

# Default: uses logged-in user credentials
client = CopilotClient()
await client.start()
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::{Client, ClientOptions};

// Default: uses logged-in user credentials
let client = Client::start(ClientOptions::default()).await?;
```

</div>

<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

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

// Default: uses logged-in user credentials
const client = new CopilotClient();
```

</div>

</div>

**何时使用**：

* 用户直接交互的桌面应用程序
* 开发和测试环境
* 用户可以以交互方式登录的任何方案

## GitHub OAuth 应用

使用 OAuth GitHub 应用通过应用程序对用户进行身份验证，并将其凭据传递给 SDK。 这使应用程序能够代表授权应用的用户发出Copilot API 请求。

**工作原理**：

1. 用户已授权您的 OAuth GitHub 应用
2. 你的应用接收用户访问令牌（`gho_` 或 `ghu_` 前缀）
3. 通过其客户端配置将令牌传递到 SDK

**SDK 配置：**

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
using GitHub.Copilot;

await using var client = new CopilotClient(new CopilotClientOptions
{
    GitHubToken = userAccessToken,     // Token from OAuth flow
    UseLoggedInUser = false,           // Don't use stored CLI credentials
});
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
import copilot "github.com/github/copilot-sdk/go"

client := copilot.NewClient(&copilot.ClientOptions{
    GitHubToken:       userAccessToken,      // Token from OAuth flow
    UseLoggedInUser:   copilot.Bool(false),  // Don't use stored CLI credentials
})
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;

var client = new CopilotClient(new CopilotClientOptions()
    .setGitHubToken(userAccessToken)  // Token from OAuth flow
    .setUseLoggedInUser(false)        // Don't use stored CLI credentials
);
client.start().get();
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from copilot import CopilotClient

client = CopilotClient({
    "github_token": user_access_token,  # Token from OAuth flow
    "use_logged_in_user": False,        # Don't use stored CLI credentials
})
await client.start()
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::{Client, ClientOptions};

let client = Client::start(
    ClientOptions::default()
        .with_github_token(user_access_token)
        .with_use_logged_in_user(false),
).await?;
```

</div>

<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

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

const client = new CopilotClient({
    gitHubToken: userAccessToken,  // Token from OAuth flow
    useLoggedInUser: false,        // Don't use stored CLI credentials
});
```

</div>

</div>

**支持的令牌类型：**

* `gho_` - OAuth 用户访问令牌
* `ghu_` - GitHub应用用户访问令牌
* `github_pat_` - 细粒度个人访问令牌

**不支持：**

* `ghp_` - 经典个人访问令牌（已弃用）

**何时使用**：

* 用户通过GitHub登录的 Web 应用程序
* 基于 Copilot 构建的 SaaS 应用程序
* 需要代表不同用户发出请求的任何多用户应用程序

有关详细信息，请参阅“[GitHub OAuth 设置](/zh/copilot/how-tos/copilot-sdk/setup/github-oauth)”。

## 轮换会话范围的GitHub令牌

对于多用户服务和集成，请为每个会话设置令牌提供程序，而不要存储单个长期有效的令牌。 运行时调用提供程序以获取实际生效的 GitHub 主机，并将该请求标识为 `initial` 或 `refresh`。 仅当云会话尚未收到其 ID 时，会话 ID 才缺席。

返回带标签的令牌结果，或显式取消。 每个令牌结果都必须包括 `expiresIn`：回调完成时剩余的正秒数。 生产GitHub令牌通常持续 8 小时，因此`8 * 60 * 60`是一个通用值。 不要同时设置静态的每会话令牌和提供程序。

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

<!-- docs-validate: skip -->

```typescript
const session = await client.createSession({
    gitHubTokenProvider: async ({ host, sessionId, reason }) => {
        const token = await acquireGitHubToken({ host, sessionId, reason });
        return {
            kind: "token",
            accessToken: token.value,
            expiresIn: token.secondsRemaining,
        };
    },
});
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

<!-- docs-validate: skip -->

```python
async def provide_github_token(args):
    token = await acquire_github_token(
        host=args["host"],
        session_id=args["session_id"],
        reason=args["reason"],
    )
    return {
        "kind": "token",
        "accessToken": token.value,
        "expiresIn": token.seconds_remaining,
    }

session = await client.create_session(github_token_provider=provide_github_token)
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

<!-- docs-validate: skip -->

```golang
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
    GitHubTokenProvider: func(args copilot.GitHubTokenProviderArgs) (*copilot.GitHubTokenProviderResult, error) {
        token, secondsRemaining, err := acquireGitHubToken(args.Host, args.SessionID, args.Reason)
        if err != nil {
            return nil, err
        }
        return copilot.GitHubTokenResult(&copilot.GitHubToken{
            AccessToken: token,
            ExpiresIn:   secondsRemaining,
        }), nil
    },
})
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

<!-- docs-validate: skip -->

```csharp
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    GitHubTokenProvider = async args =>
    {
        var token = await AcquireGitHubTokenAsync(args.Host, args.SessionId, args.Reason);
        return GitHubTokenProviderResult.FromToken(new GitHubToken
        {
            AccessToken = token.Value,
            ExpiresIn = token.SecondsRemaining,
        });
    },
});
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

<!-- docs-validate: skip -->

```java
var session = client.createSession(new SessionConfig()
    .setGitHubTokenProvider(args ->
        acquireGitHubToken(args.host(), args.sessionId(), args.reason())
            .thenApply(token -> GitHubTokenProviderResult.token(
                token.value(), token.secondsRemaining())))
    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

<!-- docs-validate: skip -->

```rust
let provider = Arc::new(|args: GitHubTokenProviderArgs| async move {
    let token = acquire_github_token(&args.host, args.session_id.as_ref(), args.reason).await?;
    Ok(GitHubTokenProviderResult::Token(GitHubToken::new(
        token.value,
        token.seconds_remaining,
    )))
});

let session = client
    .create_session(SessionConfig::default().with_github_token_provider(provider))
    .await?;
```

</div>

</div>

运行时将执行 `initial` 获取，作为会话创建或恢复的一部分。 已取消的获取、提供程序错误、无效响应，或缺少稳定帐户标识的令牌，都会导致创建或恢复操作被拒绝。 运行时不会回退到环境身份验证。

建立会话后，运行时在每个凭据使用操作之前执行异步预检。 当当前令牌的剩余时间为一小时或更短时，它会请求一个 `refresh`。 空闲会话在下一次执行消耗凭据的操作之前不会被刷新。 对于此回调，运行时不使用后台计时器、拒绝驱动的重放、401/403 质询传播或范围扩大。

## 环境变量

对于自动化、CI/CD 管道和服务器到服务器方案，可以使用环境变量进行身份验证。

有关不应使用用户个人访问令牌的组织特性化自动化，请参阅 [服务器到服务器身份验证](/zh/copilot/how-tos/copilot-sdk/auth/server-to-server-tokens)。

**支持的环境变量（按优先级顺序）：**

1. `COPILOT_GITHUB_TOKEN` - 推荐用于显式 Copilot 使用场景
2. `GH_TOKEN` - GitHub CLI 兼容
3. `GITHUB_TOKEN` - GitHub Actions兼容

**工作原理**：

1. 使用有效令牌设置受支持的环境变量之一
2. SDK 会自动检测和使用令牌

**SDK 配置：**

无需更改代码 - SDK 会自动检测环境变量：

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
using GitHub.Copilot;

// Token is read from environment variable automatically
await using CopilotClient client = new();
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
import copilot "github.com/github/copilot-sdk/go"

// Token is read from environment variable automatically
client := copilot.NewClient(nil)
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
import com.github.copilot.CopilotClient;

// Token is read from environment variable automatically
var client = new CopilotClient();
client.start().get();
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from copilot import CopilotClient

# Token is read from environment variable automatically
client = CopilotClient()
await client.start()
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::{Client, ClientOptions};

// Token is read from environment variable automatically
let client = Client::start(ClientOptions::default()).await?;
```

</div>

<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

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

// Token is read from environment variable automatically
const client = new CopilotClient();
```

</div>

</div>

**何时使用**：

* CI/CD 管道（GitHub Actions、Jenkins 等）
* 自动测试
* 具有服务帐户的服务器端应用程序
* 在不想使用交互式登录时进行开发

## BYOK （自带密钥）

BYOK 允许你从模型提供程序（如 Microsoft Foundry、OpenAI 或 Anthropic）使用自己的 API 密钥。 这会完全绕过GitHub Copilot身份验证。

**主要优势：**

* 无需GitHub Copilot订阅
* 使用企业模型部署
* 使用模型提供商进行直接计费
* 支持 Microsoft Foundry、OpenAI、Anthropic 以及与 OpenAI 兼容的端点

**有关完整详细信息，请参阅 [BYOK （自带密钥）](/zh/copilot/how-tos/copilot-sdk/auth/byok)**，包括：

* Microsoft Foundry 设置
* 提供程序配置选项
* 限制和注意事项
* 完整代码示例

## 身份验证优先级

当有多个身份验证方法可用时，SDK 会按以下优先级顺序使用这些方法：

1. **显式 `gitHubToken`** - 直接传递给 SDK 客户端或会话配置的令牌
2. **直接 API 令牌** - `GITHUB_COPILOT_API_TOKEN`，搭配 `COPILOT_API_URL` 使用
3. **环境变量令牌** - `COPILOT_GITHUB_TOKEN``GH_TOKEN` →→`GITHUB_TOKEN`
4. **已存储的 OAuth 凭据** - 来自之前的 `copilot` CLI 登录
5. **GitHub CLI** - `gh auth` 凭据

对于多用户服务器模式，请传递每会话`gitHubToken`，以便每个会话都使用正确的GitHub标识运行;请参阅 [多租户与服务器部署](/zh/copilot/how-tos/copilot-sdk/setup/multi-tenancy)。

## 禁用自动登录

若要防止 SDK 自动使用已存储的凭据或 `gh` CLI 身份验证，请将其配置为禁用已登录用户回退机制：

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
await using var client = new CopilotClient(new CopilotClientOptions
{
    UseLoggedInUser = false,  // Only use explicit tokens
});
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
client := copilot.NewClient(&copilot.ClientOptions{
    UseLoggedInUser: copilot.Bool(false),  // Only use explicit tokens
})
```

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
import com.github.copilot.CopilotClient;
import com.github.copilot.rpc.*;

var client = new CopilotClient(new CopilotClientOptions()
    .setUseLoggedInUser(false)  // Only use explicit tokens
);
client.start().get();
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
client = CopilotClient({
    "use_logged_in_user": False,  # Only use explicit tokens
})
```

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

```rust
use github_copilot_sdk::{Client, ClientOptions};

let client = Client::start(
    ClientOptions::default().with_use_logged_in_user(false),
).await?;
```

</div>

<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
const client = new CopilotClient({
    useLoggedInUser: false,  // Only use explicit tokens
});
```

</div>

</div>

## 后续步骤

* [BYOK （自带密钥）](/zh/copilot/how-tos/copilot-sdk/auth/byok) - 了解如何使用自己的 API 密钥
* [Build your first Copilot-powered app](/zh/copilot/get-started/sdk-quickstart) - 生成第一个Copilot驱动的应用
* [将 MCP 服务器与 GitHub Copilot SDK 配合使用](/zh/copilot/how-tos/copilot-sdk/features/mcp) - 连接到外部工具