Skip to main content

GitHub OAuth 설정

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

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

작동 방식

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

다이어그램: 설명된 프로세스를 보여 주는 시퀀스 다이어그램

주요 특징:

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

아키텍처

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

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 흐름을 처리합니다. 서버 쪽 토큰 교환은 다음과 같습니다.

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

지원되는 토큰 형식

토큰 접두사Source작동합니까?
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 서버를 실행하고 세션당 토큰을 전달할 수 있습니다. 이 패턴은 백 엔드 서비스 설정을 참조하세요.

Limitations

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

이동 시기

필요다음 가이드
GitHub 계정이 없는 사용자
BYOK (bring your own key)
서버에서 SDK 실행
백 엔드 서비스 설정
많은 동시 사용자 처리
확장성 및 멀티 테넌시

다음 단계