mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
## Problem
App-server clients could only initiate ChatGPT login through the browser
callback flow, even though the shared login crate already supports
device-code auth. That left VS Code, Codex App, and other app-server
clients without a first-class way to use the existing device-code
backend when browser redirects are brittle or when the client UX wants
to own the login ceremony.
## Mental model
This change adds a second ChatGPT login start path to app-server:
clients can now call `account/login/start` with `type:
"chatgptDeviceCode"`. App-server immediately returns a `loginId` plus
the device-code UX payload (`verificationUrl` and `userCode`), then
completes the login asynchronously in the background using the existing
`codex_login` polling flow. Successful device-code login still resolves
to ordinary `chatgpt` auth, and completion continues to flow through the
existing `account/login/completed` and `account/updated` notifications.
## Non-goals
This does not introduce a new auth mode, a new account shape, or a
device-code eligibility discovery API. It also does not add automatic
fallback to browser login in core; clients remain responsible for
choosing when to request device code and whether to retry with a
different UX if the backend/admin policy rejects it.
## Tradeoffs
We intentionally keep `login_chatgpt_common` as a local validation
helper instead of turning it into a capability probe. Device-code
eligibility is checked by actually calling `request_device_code`, which
means policy-disabled cases surface as an immediate request error rather
than an async completion event. We also keep the active-login state
machine minimal: browser and device-code logins share the same public
cancel contract, but device-code cancellation is implemented with a
local cancel token rather than a larger cross-crate refactor.
## Architecture
The protocol grows a new `chatgptDeviceCode` request/response variant in
app-server v2. On the server side, the new handler reuses the existing
ChatGPT login precondition checks, calls `request_device_code`, returns
the device-code payload, and then spawns a background task that waits on
either cancellation or `complete_device_code_login`. On success, it
reuses the existing auth reload and cloud-requirements refresh path
before emitting `account/login/completed` success and `account/updated`.
On failure or cancellation, it emits only `account/login/completed`
failure. The existing `account/login/cancel { loginId }` contract
remains unchanged and now works for both browser and device-code
attempts.
## Tests
Added protocol serialization coverage for the new request/response
variant, plus app-server tests for device-code success, failure, cancel,
and start-time rejection behavior. Existing browser ChatGPT login
coverage remains in place to show that the callback-based flow is
unchanged.
92 lines
2.4 KiB
JSON
92 lines
2.4 KiB
JSON
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"oneOf": [
|
|
{
|
|
"properties": {
|
|
"apiKey": {
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"enum": [
|
|
"apiKey"
|
|
],
|
|
"title": "ApiKeyv2::LoginAccountParamsType",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"apiKey",
|
|
"type"
|
|
],
|
|
"title": "ApiKeyv2::LoginAccountParams",
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"type": {
|
|
"enum": [
|
|
"chatgpt"
|
|
],
|
|
"title": "Chatgptv2::LoginAccountParamsType",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
],
|
|
"title": "Chatgptv2::LoginAccountParams",
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"type": {
|
|
"enum": [
|
|
"chatgptDeviceCode"
|
|
],
|
|
"title": "ChatgptDeviceCodev2::LoginAccountParamsType",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"type"
|
|
],
|
|
"title": "ChatgptDeviceCodev2::LoginAccountParams",
|
|
"type": "object"
|
|
},
|
|
{
|
|
"description": "[UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE. The access token must contain the same scopes that Codex-managed ChatGPT auth tokens have.",
|
|
"properties": {
|
|
"accessToken": {
|
|
"description": "Access token (JWT) supplied by the client. This token is used for backend API requests and email extraction.",
|
|
"type": "string"
|
|
},
|
|
"chatgptAccountId": {
|
|
"description": "Workspace/account identifier supplied by the client.",
|
|
"type": "string"
|
|
},
|
|
"chatgptPlanType": {
|
|
"description": "Optional plan type supplied by the client.\n\nWhen `null`, Codex attempts to derive the plan type from access-token claims. If unavailable, the plan defaults to `unknown`.",
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"type": {
|
|
"enum": [
|
|
"chatgptAuthTokens"
|
|
],
|
|
"title": "ChatgptAuthTokensv2::LoginAccountParamsType",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"accessToken",
|
|
"chatgptAccountId",
|
|
"type"
|
|
],
|
|
"title": "ChatgptAuthTokensv2::LoginAccountParams",
|
|
"type": "object"
|
|
}
|
|
],
|
|
"title": "LoginAccountParams"
|
|
} |