Skip to content

OAuth 方式让每个用户用自己的 GitHub 账号授权你的应用,使用各自的 Copilot 配额。创建 GitHub OAuth App,实现标准 OAuth 流程,每个用户单独创建 SDK 客户端并传入其 token。SDK 不管理 OAuth 生命周期,需要应用层自行处理 token 刷新。

GitHub Copilot SDK GitHub OAuth 配置:为 SaaS 应用服务多用户

适用场景

  • SaaS 应用:服务多个用户,每人用自己的 Copilot 订阅
  • 团队工具:部门内多人共用一个工具,各自的 Copilot 配额独立
  • 插件/扩展:需要用户授权才能访问 Copilot

前提条件

  • 每个用户需要有 GitHub Copilot 订阅(Free / Pro / Pro+)
  • 需要在 GitHub 创建一个 OAuth App

第一步:创建 GitHub OAuth App

  1. 进入 GitHub SettingsDeveloper settingsOAuth Apps
  2. 点击 New OAuth App,填写:
    • Application name:你的应用名
    • Homepage URL:应用首页
    • Authorization callback URL:OAuth 回调地址(如 https://your-app.com/auth/github/callback
  3. 记录 Client IDClient Secret

第二步:实现 OAuth 流程

typescript
import express from 'express'

const app = express()

// 步骤 1:引导用户到 GitHub 授权页
app.get('/auth/github', (req, res) => {
  const authUrl = new URL('https://github.com/login/oauth/authorize')
  authUrl.searchParams.set('client_id', process.env.GITHUB_CLIENT_ID!)
  authUrl.searchParams.set('scope', 'copilot')  // 申请 Copilot 访问权限
  authUrl.searchParams.set('state', generateCsrfToken(req))
  
  res.redirect(authUrl.toString())
})

// 步骤 2:处理 OAuth 回调,换取 access token
app.get('/auth/github/callback', async (req, res) => {
  const { code, state } = req.query
  
  // 验证 CSRF state
  if (!validateCsrfToken(req, state as string)) {
    return res.status(403).send('Invalid state')
  }
  
  // 用 code 换取 access token
  const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
    method: 'POST',
    headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: process.env.GITHUB_CLIENT_ID,
      client_secret: process.env.GITHUB_CLIENT_SECRET,
      code
    })
  })
  
  const { access_token } = await tokenResponse.json()
  
  // 存储用户 token(数据库/Session)
  await saveUserToken(req.session.userId, access_token)
  
  res.redirect('/dashboard')
})

第三步:为每个用户创建 SDK 客户端

typescript
import { createSession } from '@github/copilot-sdk'

// 每个用户请求单独创建 Session,传入该用户的 token
async function handleUserRequest(userId: string, userPrompt: string) {
  const userToken = await getUserToken(userId)
  
  const session = await createSession({
    auth: {
      type: 'oauth',
      clientId: process.env.GITHUB_CLIENT_ID!,
      token: userToken
    }
  })
  
  const response = await session.sendPrompt({
    messages: [{ role: 'user', content: userPrompt }]
  })
  
  return response.content
}

多用户隔离

每个用户使用独立的 Session,确保用户之间完全隔离:

typescript
// 推荐:用 userId 作为 sessionId 前缀,便于管理
const session = await createSession({
  auth: { type: 'oauth', token: userToken },
  sessionId: `user-${userId}-${Date.now()}`
})

验证用户的组织归属(可选)

如果需要限制只有特定组织成员才能访问:

typescript
async function isUserInOrg(token: string, orgName: 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 === orgName)
}

// 在创建 Session 前检查
if (!await isUserInOrg(userToken, 'your-org-name')) {
  throw new Error('只有 your-org-name 组织成员才能使用此功能')
}

Token 类型说明

支持的 GitHub token 前缀:

前缀类型
gho_OAuth access token
ghu_User-to-server token(GitHub App)
github_pat_Fine-grained Personal Access Token

常见问题

Q: Token 过期后怎么处理?

A: GitHub OAuth token 没有过期时间,除非用户主动撤销授权。但 Fine-grained PAT 有过期时间,需要定期提醒用户更新。SDK 不管理 token 生命周期,检测到 401 错误时需要引导用户重新授权。

Q: 同一用户可以有多个并发 Session 吗?

A: 技术上可以,但每个 Session 消耗该用户的 Copilot Premium Request 配额。如果并发 Session 过多,可能导致用户额度快速耗尽。

Q: 是否需要存储 access_token?

A: 是的。OAuth token 只在换取时返回一次,如果不存储就无法复用。建议加密后存入数据库,不要存明文。