mcpField
L
login-with-chatgpt

login-with-chatgpt

github.com/opencoredev开发33877 次安装5 天前更新
代码仓库

关于 login-with-chatgpt

login-with-chatgpt 是用于在 Web 应用中接入 ChatGPT 账户登录及服务端 Responses 调用的 SDK,包含服务端、React 和 AI SDK 包,并默认将令牌留在服务端。

主要功能

  1. 01ChatGPT 设备流登录
  2. 02基于 Cookie 的会话管理
  3. 03流式 Responses 代理
  4. 04按账户发现可用模型
  5. 05React 登录组件与 Hook
  6. 06AI SDK 文本、工具和图像支持

适用场景

  1. 01为 Web 应用添加 ChatGPT 登录
  2. 02通过服务端路由流式传输模型响应
  3. 03选择登录账户可用的模型
  4. 04使用 AI SDK 生成或编辑图像

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/opencoredev/login-with-chatgpt --skill login-with-chatgpt

安装后在 Claude Code 中输入/login-with-chatgpt确认已加载。

详细介绍

使用 ChatGPT 登录

用于“使用 ChatGPT 账户登录”的 SDK。用户通过 OpenAI 的设备流程进行身份验证;处理程序保留令牌,并将 Responses 风格的调用代理到由 ChatGPT 提供支持的 Codex 端点。 浏览器中始终只保存 HttpOnly 会话 Cookie。

规则:编写代码前请阅读

  1. 没有 API 密钥。 身份验证来自每位用户的 ChatGPT 会话。 切勿添加 OPENAI_API_KEY,也切勿在此流程中直接调用 api.openai.com。请求应通过应用自身的 /api/chatgpt/responses 代理,或 基于 auth.proxyFetch(request) 构建的服务端路由发送。
  2. 选择模型前先查询。 模型可用性因账户和套餐而异。调用 await chatgpt.listModels()(浏览器端)或 await auth.getModels(request)(服务端),然后从结果中选择。 可以使用硬编码的 allowedModels 作为限制,但不能假设每个已登录账户都能使用同一个模型。
  3. 默认情况下,令牌仅保留在处理程序内部。 不要构建向客户端返回令牌的端点。常规应用代码应使用 /responses、 /models 或 auth.proxyFetch(request)。导出原始令牌必须显式启用 dangerouslyAllowTokenExport 这一逃逸开关。
  4. 不能省略用户同意步骤。 组件始终会在 OpenAI 验证页面之前显示同意步骤。自定义 UI 必须在调用 login() 之前 呈现等效的同意步骤。
  5. 生产环境需要稳定的 secret 和共享的 sessionStore。 默认值(临时密钥、内存存储)会导致每次重启后所有用户都退出登录, 并且在无服务器实例之间无法正常工作。

软件包

软件包用途
@opencoredev/loginwithchatgpt-server用于登录、会话、登出、模型和流式代理的 createChatGPTHandler()
@opencoredev/loginwithchatgpt-react<LoginWithChatGPT /> 按钮、useLoginWithChatGPT() Hook
@opencoredev/loginwithchatgpt-aiVercel AI SDK 提供程序(ai 和 @ai-sdk/openai 是 peer 依赖)
@opencoredev/loginwithchatgpt-core底层 OAuth/设备流程、错误和类型;很少直接导入
bun add @opencoredev/loginwithchatgpt-server @opencoredev/loginwithchatgpt-react @opencoredev/loginwithchatgpt-ai ai @ai-sdk/openai

服务端处理程序

一个处理程序负责处理 basePath(默认为 /api/chatgpt)下的所有内容。它基于 Web 标准的 Request、Response、fetch 和 crypto.subtle 编写,因此应在提供这些 API 的运行时中使用。

// Next.js: app/api/chatgpt/[...lwc]/route.ts
import { createChatGPTHandler } from "@opencoredev/loginwithchatgpt-server";

const auth = createChatGPTHandler({
  secret: process.env.LWC_SECRET, // openssl rand -hex 32
  responsesProxy: {
    allowedModels: ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"],
  },
});

export const GET = (request: Request) => auth.handler(request);
export const POST = (request: Request) => auth.handler(request);
// Bun
Bun.serve({
  routes: {
    "/": index,
    "/api/chatgpt/*": (req) => auth.handler(req),
  },
});

主要选项:basePath、secret、sessionStore(任何 get/set/delete 键值存储)、cookieName、cookie、 sessionTtlMs(30 天)、defaultModel("gpt-5.5")、 enableResponsesProxy(设为 false 时也会禁用 /models)、responsesProxy (allowedModels、maxRequestBytes 40 MiB、rateLimit 默认 30 次/分钟/会话)、allowedOrigins(跨源 CSRF 允许列表)。

返回的处理程序提供的服务端辅助方法(均会读取会话 Cookie):

  • auth.getSession(request) → { status, user? };不会调用上游服务。
  • auth.proxyFetch(request) → 用于自定义服务端 AI 路由的请求级 fetch,不会暴露原始 bearer 令牌。
  • auth.getModels(request) → 账户的模型标识符,或 undefined。
  • auth.dangerouslyGetTokens(request) → 原始令牌逃逸开关;需要启用 dangerouslyAllowTokenExport。

React 登录

"use client";
import { LoginWithChatGPT } from "@opencoredev/loginwithchatgpt-react";

<LoginWithChatGPT
  consent={{ appName: "Acme" }}
  onAuthenticated={(user) => console.log("connected", user?.email)}
/>;

此组件会处理完整流程:同意弹窗 → OpenAI 验证 → 复制代码 → 轮询 → 显示带有断开连接选项的已登录状态标记。可通过注入的 .lwc-* 类重新设置样式,或传入 children 渲染函数以实现完全自定义的 UI(此时需自行呈现同意步骤,并使用 openLoginWithChatGPTConsentPopup())。

对于自定义 UI,useLoginWithChatGPT({ basePath?, pollIntervalMs?, ... }) 会返回 { status, user, userCode, verificationUrl, login, logout, copyCode, reopen, isAuthenticated, isPending }。status 的值可以是 loading | unauthenticated | connecting | pending | authenticated | expired | error。

使用 AI SDK 进行流式传输

浏览器代理提供方,从 cookie 在服务端注入凭据:

import { createChatGPTProxyProvider } from "@opencoredev/loginwithchatgpt-ai";
import { streamText } from "ai";

const chatgpt = createChatGPTProxyProvider(); // { basePath } if not /api/chatgpt

const models = await chatgpt.listModels(); // throws ChatGPTProxyError; status 401 = signed out
const model = models.includes("gpt-5.5") ? "gpt-5.5" : models[0];

const result = streamText({ model: chatgpt(model), prompt });

用于自有 AI 路由的服务端代理提供方:

import { createChatGPTProxyProvider } from "@opencoredev/loginwithchatgpt-ai";
import { streamText } from "ai";

export async function POST(request: Request) {
  const chatgpt = createChatGPTProxyProvider({
    fetch: auth.proxyFetch(request),
  });
  const { prompt } = await request.json();
  return streamText({ model: chatgpt(), prompt }).toUIMessageStreamResponse();
}

模型支持 streamText、generateText、工具调用、结构化输出,以及通过标准 AI SDK messages 附加文件。图像是提供方 API 的一等功能:使用 chatgpt.images.generate() 通过提示词生成图像,使用 chatgpt.images.edit() 编辑图像;支持多个参考图、蒙版、输入保真度、自定义尺寸、质量、格式、压缩、背景、多个输出和部分图像回调。两者都通过 /responses 使用已登录用户的 ChatGPT 套餐;无需添加 API 密钥。不提供嵌入和音频功能。

POST /responses 请求级调优请求头: x-login-with-chatgpt-reasoning-effort(none|low|medium|high|xhigh)和 x-login-with-chatgpt-service-tier(auto|default|flex|priority|fast)。

HTTP 路由(相对于 basePath)

路由用途
POST /login启动设备登录 → { status: "pending", userCode, verificationUrl, interval, expiresAt }
GET /status通过一次轮询推进登录流程,并返回状态
GET /session读取状态(开销低),不会轮询上游
POST /logout删除会话并清除 cookie
GET /models账户的模型 slug(未登录时返回 401)
POST /responses流式 Responses 风格代理

非 GET 路由会基于 Origin 执行 CSRF 防护:仅允许同源请求或 allowedOrigins 中的来源。前后端分离部署还需要 SameSite=None cookie、携带凭据的 fetch 请求和 CORS 请求头(参见跨域指南)。

生产环境检查清单

  • 设置 LWC_SECRET(在各次部署间保持稳定;轮换后会让所有用户退出登录)。
  • 使用共享的 sessionStore(Redis/DB)。MemoryStore 仅用于开发环境。
  • 设置 responsesProxy.allowedModels;运行多个实例时,传入共享的 rateLimit.store。
  • 使用 HTTPS,并转发 X-Forwarded-Proto,以便为 cookie 设置 Secure。
  • 记录 /responses 元数据(会话 ID、模型、状态、耗时),绝不记录提示词或附件。

错误

ChatGPTAuthError(来自 core)包含 .code、.status、.body。值得注意的代码:refresh_token_invalid(会话已失效;处理程序会删除会话并报告 expired;可使用 isRefreshTokenInvalid(error) 检测)、not_authenticated、token_refresh_failed(可重试)、models_request_failed。浏览器提供方的 listModels() 会抛出带有 .status 的 ChatGPTProxyError。来自 /responses 的 HTTP 错误:401 not_authenticated、403 model_not_allowed / origin_not_allowed、413 responses_request_too_large、429 rate_limited(附带 retry-after)。

文档

完整文档位于仓库的 docs/content/docs/ 下(quickstart、concepts/security、guides/production、reference/*)。文档站点还提供 /llms.txt 和各页面的 Markdown 文件,路径为 /llms.mdx/docs/<path>/content.md。

评论

支持 Markdown