@opencoredev/loginwithchatgpt-server
v0.2.0
Published
Server handler for Login with ChatGPT: device login, session status, logout, model discovery, and an authenticated Codex responses proxy.
Maintainers
Readme
@opencoredev/loginwithchatgpt-server
Backend handler for Login with ChatGPT.
It exposes login, status, session, logout, model discovery, and responses proxy
routes from one Web-standard (Request) => Response handler.
import { createChatGPTHandler } from "@opencoredev/loginwithchatgpt-server";
const auth = createChatGPTHandler({
basePath: "/api/chatgpt",
secret: process.env.LWC_SECRET,
responsesProxy: {
allowedModels: ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"],
maxRequestBytes: 8 * 1024 * 1024,
},
});
Bun.serve({
routes: {
"/api/chatgpt/*": (req) => auth.handler(req),
},
});Routes
| Method | Path | Purpose |
| --- | --- | --- |
| POST | /login | Start or reuse a pending device-code login. |
| GET | /status | Advance one poll and return public status. |
| GET | /session | Return public status without polling. |
| POST | /logout | Delete the session and clear the cookie. |
| GET | /models | Return available model slugs for the signed-in account. |
| POST | /responses | Proxy an authenticated streaming responses request. |
Helpers
const session = await auth.getSession(request);
const models = await auth.getModels(request);
const proxyFetch = auth.proxyFetch(request);Security defaults
- Tokens are encrypted at rest (AES-GCM) when
secretis configured, and the session cookie is HttpOnly and HMAC-signed. - Normal app code uses
/responses,/models, orproxyFetch(request), so raw bearer tokens stay inside the handler. - Raw token export is disabled by default.
dangerouslyGetTokens()requiresdangerouslyAllowTokenExport: true; refresh-token export additionally requiresdangerouslyAllowRefreshTokenExport: true. /responsesis rate limited per session (30 requests/minute by default) viaresponsesProxy.rateLimit; requests through it spend the signed-in user's own ChatGPT plan.- Cookie-authenticated non-GET routes reject cross-origin browser requests
unless the origin is listed in
allowedOrigins.
Production apps should set secret and provide a shared sessionStore.
They should also restrict the built-in proxy with
responsesProxy.allowedModels and responsesProxy.maxRequestBytes (or set
enableResponsesProxy: false and build a narrower proxy), and back
responsesProxy.rateLimit with a shared store when running multiple instances.
