Skip to main content

Using GitHub OAuth with Copilot SDK

Let users authenticate with their GitHub accounts to use GitHub Copilot through your application.

谁可以使用此功能?

GitHub Copilot SDK 适用于所有 Copilot 计划。

注意

Copilot SDK is currently in 技术预览版. Functionality and availability are subject to change.

"Connect users to GitHub Copilot by providing GitHub account authentication directly within your application.

Best for: Multi-user apps, internal tools with organization access control, SaaS products, and apps where users already have GitHub accounts.

How it works

You create a GitHub OAuth App (or GitHub App), users authorize it, and you pass their access token to the SDK. Copilot requests are made on behalf of each authenticated user, using their Copilot subscription. For detailed sequence diagrams of this flow and architecture, see the github/copilot-sdk repository.

Key characteristics:

  • Each user authenticates with their own GitHub account.
  • Copilot usage is billed to each user's subscription.
  • Supports GitHub organizations and enterprise accounts.
  • Your app never handles model API keys—GitHub manages everything.

Step 1: Create a GitHub OAuth App

  1. Go to GitHub Settings > Developer Settings > OAuth Apps > New OAuth App. For organizations, go to Organization Settings > Developer Settings.
  2. Fill in the following fields:
    • Application name: Your app's name.
    • Homepage URL: Your app's URL.
    • Authorization callback URL: Your OAuth callback endpoint (for example, https://YOUR-APP.com/auth/callback). Replace YOUR-APP.com with your domain.
  3. Note your Client ID and generate a Client Secret.

注意

Both GitHub Apps and OAuth Apps work with the SDK. GitHub Apps offer finer-grained permissions and are recommended for new projects. OAuth Apps are simpler to set up. The token flow is the same from the SDK's perspective.

Step 2: Implement the OAuth flow

Your application handles the standard GitHub OAuth flow. The following shows the server-side token exchange:

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

Step 3: Pass the token to the SDK

Create an SDK client for each authenticated user, passing their token.

Node.js / 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 sign-in
    });
}

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

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

Replace USER-ACCESS-TOKEN with the user's OAuth access token (for example, gho_xxxx).

Python

from copilot import CopilotClient, 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("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({"prompt": "Hello!"})

Go

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

// Usage
client := createClientForUser("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

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

// Usage
await using var client = CreateClientForUser("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!" });

Enterprise and organization access

GitHub OAuth naturally supports enterprise scenarios. When users authenticate with GitHub, their organization memberships and enterprise associations are included.

Verify organization membership

After OAuth, you can check that the user belongs to your organization:

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, "YOUR-ORG")) {
    throw new Error("User is not a member of the required organization");
}
const client = createClientForUser(token);

Replace YOUR-ORG with your GitHub organization name.

Enterprise Managed Users (EMU)

For 托管用户帐户, the flow is identical. EMU users authenticate through GitHub OAuth like any other user, and enterprise policies (IP restrictions, SAML SSO) are enforced by GitHub automatically.

// No special SDK configuration needed for EMU
const client = new CopilotClient({
    githubToken: emuUserToken,
    useLoggedInUser: false,
});

Supported token types

Token prefixSourceSupported
gho_OAuth user access tokenYes
ghu_GitHub App user access tokenYes
github_pat_Fine-grained personal access tokenYes
ghp_Personal access token (classic)No (弃用)

Token lifecycle management

Your application is responsible for token storage, refresh, and expiration handling. The SDK uses whatever token you provide—it doesn't manage the OAuth lifecycle.

Token refresh pattern

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

Multi-user patterns

Each user gets their own SDK client with their own token. This provides the strongest isolation.

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)!;
}

Limitations

LimitationDetails
Copilot subscription requiredEach user needs an active GitHub Copilot subscription.
Token management is your responsibilityYou must store, refresh, and handle token expiration.
GitHub account requiredUsers must have GitHub accounts.
Rate limits per userUsage is subject to each user's Copilot rate limits.

Next steps