站长自营 API 中转

正在比较模型套餐?可以把多个 AI API 接到一个网关里

ZZSwitch 是我自己运营的统一 API 网关,适合需要国内支付、兑换码充值、多模型切换和 OpenAI 兼容接口的开发者。不是 OpenCode 官方服务。

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

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 客户端

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,确保用户之间完全隔离:

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

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

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

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 只在换取时返回一次,如果不存储就无法复用。建议加密后存入数据库,不要存明文。

站长自营 API 中转

ZZSwitch API 中转

统一接入多家模型,支持兑换码充值。

打开 ZZSwitch