Best for: aplicaciones multiusuario, herramientas internas con control de acceso de la organización, productos SaaS, aplicaciones donde los usuarios tienen cuentas de GitHub.
Cómo funciona
Creas una aplicación OAuth de GitHub (o una GitHub App), los usuarios la autorizan y pasas su token de acceso al SDK. Las solicitudes de Copilot se realizan en nombre de cada usuario autenticado, usando su suscripción de Copilot.

Características principales:
- Cada usuario se autentica con su propia cuenta de GitHub
- El uso de Copilot se factura a la suscripción de cada usuario.
- Admite organizaciones de GitHub y cuentas Enterprise
- La aplicación nunca controla las claves de API del modelo, GitHub administra todo
Architecture

Paso 1: crear una aplicación de GitHub OAuth
-
Vaya a GitHub Configuración → Configuración del desarrollador → Aplicaciones de OAuth → Nueva aplicación de OAuth (o para organizaciones: Configuración de organización → Configuración del desarrollador)
-
Rellene:
- Nombre de la aplicación: nombre de la aplicación
- Dirección URL de la página principal: dirección URL de la aplicación
- URL de callback de autorización: Su endpoint de callback de OAuth (p. ej.,
https://yourapp.com/auth/callback)
-
Anote el identificador de cliente y genere un secreto de cliente.
GitHub App vs OAuth App: Ambos funcionan. GitHub Apps ofrecen permisos más específicos y se recomiendan para los nuevos proyectos. Las aplicaciones de OAuth son más sencillas de configurar. El flujo de tokens es el mismo desde la perspectiva del SDK.
Paso 2: implementar el flujo de OAuth
La aplicación controla el flujo estándar de GitHub OAuth. Este es el intercambio de tokens del lado servidor:
// 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
}
Paso 3: pasar el token al SDK
Cree un cliente del SDK para cada usuario autenticado y pase su token:
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!" });
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!")
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!"})
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!" });
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();
}
Acceso empresarial y organizacional
GitHub OAuth admite naturalmente escenarios empresariales. Cuando los usuarios se autentican con GitHub, sus pertenencias a la organización y las asociaciones empresariales se unen.

Comprobación de la pertenencia a la organización
Después de OAuth, compruebe que el usuario pertenece a su organización:
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);
Usuarios administrados por la empresa (EMU)
Para los Enterprise Managed Users de GitHub, el flujo es idéntico: los usuarios de EMU se autentican mediante GitHub OAuth como cualquier otro usuario. GitHub aplica automáticamente sus políticas empresariales (restricciones de IP, inicio de sesión único mediante SAML).
// 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,
});
Tipos de token admitidos
| Prefijo de token | Source | ¿Trabajas? |
|---|---|---|
gho_ | Token de acceso de usuario de OAuth | ✅ |
ghu_ | token de acceso de usuario de GitHub app | ✅ |
github_pat_ | Token de acceso personal específico | ✅ |
ghp_ | Token de acceso personal clásico | |
| ❌ (en desuso) |
Ciclo de vida de los tokens

Importante: La aplicación es responsable del almacenamiento de tokens, la actualización y el control de expiración. El SDK usa el token que proporcione: no administra el ciclo de vida de OAuth.
Patrón de actualización de tokens
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");
}
Patrones multiusuario
Un cliente por usuario (recomendado)
Cada usuario obtiene su propio cliente del SDK con su propio token. Esto proporciona el aislamiento más fuerte.
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 compartida con tokens por solicitud
Para un menor consumo de recursos, puede ejecutar un único servidor CLI externo y pasar tokens en cada sesión. Consulte Configuración de servicios back-end para obtener este patrón.
Limitaciones
| Limitación | Detalles |
|---|---|
| Se requiere una suscripción a Copilot | Cada usuario necesita una suscripción de Copilot activa |
| La administración de tokens es su responsabilidad | Almacenar, actualizar y controlar la expiración |
| GitHub cuenta necesaria | Los usuarios deben tener cuentas de GitHub |
| Límites de velocidad por usuario | Sujeto a los límites de velocidad de Copilot de cada usuario |
Cuándo seguir adelante
| Requisito | Guía siguiente |
|---|---|
| Usuarios sin cuentas de GitHub | |
| BYOK (bring your own key) | |
| Ejecución del SDK en servidores | |
| Configuración de servicios back-end | |
| Control de muchos usuarios simultáneos | |
| Escalabilidad y multitenencia |
Pasos siguientes
- Autenticación: Referencia completa del método de autenticación
- Configuración de servicios back-end: Ejecutar el SDK en el servidor
- Escalabilidad y multitenencia: Gestiona muchos usuarios a gran escala