# GitHub OAuth 설정

사용자가 애플리케이션을 통해 Copilot 사용하도록 GitHub 계정으로 인증할 수 있습니다. 개별 계정, 조직 멤버 자격 및 엔터프라이즈 ID를 지원합니다.

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

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

**Best for:** 다중 사용자 앱, 조직 액세스 제어가 있는 내부 도구, SaaS 제품, 사용자가 GitHub 계정이 있는 앱.

## 작동 방식

GitHub OAuth 앱(또는 GitHub 앱을 만들고, 사용자가 권한을 부여하고, 해당 액세스 토큰을 SDK에 전달합니다. Copilot 요청은 Copilot 구독을 사용하여 인증된 각 사용자를 대신하여 이루어집니다.

![다이어그램: 설명된 프로세스를 보여 주는 시퀀스 다이어그램](/assets/images/help/copilot/copilot-sdk/setup-github-oauth-diagram-0.png)

**주요 특징:**

* 각 사용자는 자신의 GitHub 계정으로 인증합니다.
* Copilot 사용량은 각 사용자의 구독에 청구됩니다.
* GitHub 조직 및 엔터프라이즈 계정 지원
* 앱은 모델 API 키를 처리하지 않습니다. GitHub 모든 것을 관리합니다.

## 아키텍처

![다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.](/assets/images/help/copilot/copilot-sdk/setup-github-oauth-diagram-1.png)

## 1단계: GitHub OAuth 앱 만들기

1. **GitHub 설정 → 개발자 설정 → OAuth 앱 → 새 OAuth 앱**(또는 조직: \*\* 개발자 설정 → 구성 설정\*\*)으로 이동합니다.

2. 다음을 입력합니다.
   * **애플리케이션 이름**: 앱 이름
   * **홈페이지 URL**: 앱의 URL
   * **권한 부여 콜백 URL**: OAuth 콜백 엔드포인트(예: `https://yourapp.com/auth/callback`)

3. **클라이언트 ID**를 확인하고 **클라이언트 암호를** 생성합니다.

> **GitHub 앱과 OAuth App:** 모두 작동합니다. GitHub 앱은 세분화된 권한을 제공하며 새 프로젝트에 권장됩니다. OAuth 앱은 설정하는 것이 더 간단합니다. 토큰 흐름은 SDK의 관점에서 동일합니다.

## 2단계: OAuth 흐름 구현

애플리케이션은 표준 GitHub OAuth 흐름을 처리합니다. 서버 쪽 토큰 교환은 다음과 같습니다.

```typescript
// 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 클라이언트를 만들고 해당 토큰을 전달합니다.

<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>

```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-5.4",
});

const response = await session.sendAndWait({ prompt: "Hello!" });
```

</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
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-5.4", session_id=f"user-{user_id}-session")

response = await session.send_and_wait("Hello!")
```

</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
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-5.4",
})
response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"})
```

</div>

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

```csharp
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-5.4",
});

var response = await session.SendAndWaitAsync(
    new MessageOptions { Prompt = "Hello!" });
```

</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.*;

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-5.4")
        .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

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

</div>

</div>

## 엔터프라이즈 및 조직 액세스

GitHub OAuth는 자연스럽게 엔터프라이즈 시나리오를 지원합니다. 사용자가 GitHub 인증하면 조직 멤버 자격 및 엔터프라이즈 연결이 함께 제공됩니다.

![다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.](/assets/images/help/copilot/copilot-sdk/setup-github-oauth-diagram-2.png)

### 조직 멤버 자격 확인

OAuth 후 사용자가 조직에 속하는지 확인합니다.

```typescript
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 자동으로 적용됩니다.

```typescript
// 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,
});
```

## 지원되는 토큰 형식

| 토큰 접두사          | Source              | 작동합니까? |
| --------------- | ------------------- | ------ |
| `gho_`          | OAuth 사용자 액세스 토큰    | ✅      |
| `ghu_`          | GitHub 앱 사용자 액세스 토큰 | ✅      |
| `github_pat_`   | 세분화된 개인용 액세스 토큰     | ✅      |
| `ghp_`          | 클래식 개인용 액세스 토큰      |        |
| ❌(더 이상 사용되지 않음) |                     |        |

## 토큰 수명 주기

![다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.](/assets/images/help/copilot/copilot-sdk/setup-github-oauth-diagram-3.png)

**중요:** 애플리케이션은 토큰 스토리지, 새로 고침 및 만료 처리를 담당합니다. SDK는 사용자가 제공하는 토큰을 사용하며 OAuth 수명 주기를 관리하지 않습니다.

### 토큰 새로 고침 패턴

```typescript
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 클라이언트를 가져옵니다. 이렇게 하면 가장 강력한 격리가 제공됩니다.

```typescript
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 서버를 실행하고 세션당 토큰을 전달할 수 있습니다. 이 패턴은 [백 엔드 서비스 설정](/ko/copilot/how-tos/copilot-sdk/setup/backend-services)을 참조하세요.

## Limitations

| Limitation             | Details                       |
| ---------------------- | ----------------------------- |
| **Copilot 구독 필요**      | 각 사용자에게 활성 Copilot 구독이 필요합니다. |
| **토큰 관리는 사용자의 책임입니다.** | 만료 저장, 새로 고침 및 처리             |
| **GitHub 계정이 필요합니다**   | 사용자에게 GitHub 계정이 있어야 합니다.     |
| **사용자당 속도 제한**         | 각 사용자의 Copilot 속도 제한이 적용됩니다.  |

## 이동 시기

| 필요                                                                    | 다음 가이드 |
| --------------------------------------------------------------------- | ------ |
| GitHub 계정이 없는 사용자                                                     |        |
| [BYOK(사용자 고유의 키 가져오기)](/ko/copilot/how-tos/copilot-sdk/auth/byok)     |        |
| 서버에서 SDK 실행                                                           |        |
| [백 엔드 서비스 설정](/ko/copilot/how-tos/copilot-sdk/setup/backend-services) |        |
| 많은 동시 사용자 처리                                                          |        |
| [확장성 및 멀티 테넌시](/ko/copilot/how-tos/copilot-sdk/setup/scaling)         |        |

## 다음 단계

* **[인증](/ko/copilot/how-tos/copilot-sdk/auth/authenticate)**: 전체 인증 메서드 참조
* **[백 엔드 서비스 설정](/ko/copilot/how-tos/copilot-sdk/setup/backend-services)**: SDK 서버 쪽 실행
* **[확장성 및 멀티 테넌시](/ko/copilot/how-tos/copilot-sdk/setup/scaling)**: 대규모 사용자 처리하기