Add "Sign in with Device Code" to handle `localhost:1455` OAuth callback issues
Hello there! First of all, thank you for the Codex extension and the possibility to sign in directly with our account rather than just using an API token - that's really appreciated.
That said, I ran into a recurring auth issue in my Windows + WSL workflow that I think could be solved by exposing the Device Code login in the extension UI. I spent about an hour digging into this to understand what was actually going on, so here's everything I found.
What happened
I use the OpenAI VS Code extension (openai.chatgpt) on Windows 11 and also work in WSL. In practice I often have two Codex contexts:
- VS Code on Windows
- VS Code connected to WSL (and/or configured to "run Codex in WSL")
The current "Sign in with ChatGPT" flow relies on a browser redirect to a fixed localhost callback:
http://localhost:1455/auth/callback?...
This doesn't always work well in Windows+WSL multi-instance setups because Windows localhost and WSL localhost are different contexts. It can lead to:
- Timeouts in the Windows browser (nothing responds on Windows
localhost:1455), - State mismatch when manually calling the callback in WSL (listener/session does not match the state generated by the browser flow).
The Codex docs recommend Device Code authentication for remote/headless or localhost-callback-blocked setups, but the VS Code extension UI only offers:
- "Sign in with ChatGPT"
- "Use API Key"
Feature request: please add a third option: "Sign in with Device Code" (equivalent to codex login --device-auth).
---
Environment
- OS: Windows 11
- VS Code: 1.109.4
- Extension identifier:
openai.chatgpt - Extension version: 0.4.76
- Subscription: ChatGPT Business (Google SSO + MFA)
- Settings involved:
chatgpt.runCodexInWindowsSubsystemForLinux: true/falseremote.openBrowserInRemote: true/false
---
Key multi-instance behavior (important)
I can reproduce two different behaviors depending on settings:
Case A: works, and logs in both instances
If I set:
chatgpt.runCodexInWindowsSubsystemForLinux: falseremote.openBrowserInRemote: false
and restart VS Code, sign-in succeeds.
Weird thing: after signing in with these settings, I ended up authenticated in both contexts (Windows VS Code and WSL VS Code). So the Windows-host sign-in somehow populates credentials that both instances can use. Also, when switching back to false after a failed auth attempt in WSL mode, my Windows Codex instance automatically starts working again without needing to re-authenticate.
Case B: fails in multi-instance / WSL mode
If I set:
chatgpt.runCodexInWindowsSubsystemForLinux: true
(and/or I'm actively working with a WSL VS Code instance), then the browser-based sign-in often fails at the localhost callback step:
- Windows browser times out when opening
http://localhost:1455/auth/callback?... - In WSL, calling the callback can return
State mismatch
This makes sign-in inconsistent when multiple instances/contexts are present.
---
Steps to reproduce (Case B)
- On Windows 11, open VS Code with
openai.chatgptinstalled. - Enable
chatgpt.runCodexInWindowsSubsystemForLinux: true. - Click "Sign in with ChatGPT", complete Google SSO + MFA.
- Browser redirects to
http://localhost:1455/auth/callback?code=...&state=.... - The callback page times out ("localhost took too long to respond"), and the extension remains unauthenticated.
---
Workarounds
- Setting Codex to Windows mode:
chatgpt.runCodexInWindowsSubsystemForLinux: falseremote.openBrowserInRemote: false- Restart VS Code → sign-in succeeds reliably (WSL itself still works normally).
- Manual curl from WSL: in some cases, manually calling the callback URL from inside WSL with
curl -Lvreaches the listener and can complete the auth (see logs below). This indicates the listener is inside WSL, not on Windows localhost.
---
Evidence / logs
Windows during sign-in timeout
Browser (Firefox) is trying to connect to Windows localhost:1455:
PS> netstat -ano | findstr :1455
TCP 127.0.0.1:57644 127.0.0.1:1455 SYN_SENT 9388
TCP 127.0.0.1:57645 127.0.0.1:1455 SYN_SENT 9388
PS> tasklist /fi "PID eq 9388"
firefox.exe 9388
Interpretation: Firefox on Windows attempts to connect to Windows 127.0.0.1:1455, but the TCP handshake never completes (SYN_SENT), consistent with the timeout. This suggests the callback listener is not on Windows localhost.
When WSL is set to false, the callback listener is only started during an active sign-in attempt
PS> netstat -ano | findstr :1455
(no output)
This is expected: with WSL disabled for Codex, the listener starts on the Windows side only when a sign-in is actively initiated, and the callback completes normally. Outside of that, nothing listens on 1455.
WSL shows a listener on 127.0.0.1:1455 (but without process attribution)
$ sudo ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 127.0.0.1:1455 0.0.0.0:* (no process shown)
Note: other listeners (e.g. node) show process info, but port 1455 does not. Additionally:
$ sudo lsof -nP -iTCP:1455 -sTCP:LISTEN
(no output)
$ sudo fuser -v 1455/tcp
(no output)
Despite missing process attribution, the callback endpoint does respond (see below).
WSL manual callback can fail with State mismatch
$ curl -Lv "http://localhost:1455/auth/callback?code=<redacted>&state=<redacted>"
* Host localhost:1455 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:1455...
* connect to ::1 port 1455 failed: Connection refused
* Trying 127.0.0.1:1455...
* Established connection to localhost (127.0.0.1 port 1455)
> GET /auth/callback?code=<redacted> HTTP/1.1
< HTTP/1.1 400 Bad Request
< Server: tiny-http (Rust)
< Content-Length: 14
State mismatch
Interpretation: a callback server exists inside WSL and is validating OAuth state, but in multi-instance scenarios the listener/session may not match the state generated by the browser flow, causing State mismatch. Note that -L follows redirects (e.g. to /success when it works). When it fails in multi-instance mode, it returns HTTP 400 with State mismatch.
This suggests the callback listener can belong to a different Codex/VS Code instance than the one that generated the OAuth state, so even when reachable the flow can fail in multi-instance setups.
WSL networking evidence (IPv6 refused, IPv4 served)
$ sudo tcpdump -i lo -nn "tcp port 1455" -c 20
19:37:42.468179 IP6 ::1.43251 > ::1.1455: Flags [S], seq ..., length 0
19:37:42.468187 IP6 ::1.1455 > ::1.43251: Flags [R.], ack ..., length 0 (IPv6 refused)
$ curl -v http://localhost:1455/
* Trying [::1]:1455... Connection refused
* Trying 127.0.0.1:1455... Connected
> GET / HTTP/1.1
< HTTP/1.1 404 Not Found
< Server: tiny-http (Rust)
Not Found
Interpretation: in WSL, localhost resolves to ::1 (IPv6) first; the listener appears bound to 127.0.0.1 (IPv4) only, so the first attempt is refused before falling back to IPv4. This is separate from the Windows timeout problem, but highlights how "localhost" behavior can vary across contexts.
Browser observations on the auth page (possibly secondary)
After completing Google SSO + MFA, before the localhost callback times out, the auth page showed:
- A message like "waiting for browser-intake / datahog" (wording may vary)
- Datadog-related scripts loaded from:
https://auth-cdn.oaistatic.com/assets/datadog-<hash>.js
Browser console warnings (summary):
- Content-Security-Policy warnings around
strict-dynamic - Cookies rejected for invalid domain (
__cf_bm,oai-sc) - Source map 404 for some assets (
*.js.map)
These warnings may be unrelated to the root cause (localhost callback/context mismatch), but I'm including them in case they help correlate where the flow hangs.
---
What this shows
- The browser-based sign-in assumes
http://localhost:1455/...is reachable from the browser host. - In Windows+WSL workflows, "localhost" can refer to different network namespaces (Windows vs WSL).
- In multi-instance scenarios, even when WSL has a listener, the flow can fail with
State mismatchdue to session/state belonging to another instance. - Running sign-in on Windows (
chatgpt.runCodexInWindowsSubsystemForLinux: false) works and can even authenticate both instances, which suggests the credential storage/visibility differs between modes.
---
Feature request
Add a third sign-in option in the VS Code extension:
Sign in with Device Code (equivalent to codex login --device-auth)
This avoids localhost callbacks entirely and should be the recommended option for:
- WSL
- Remote-SSH
- devcontainers
- Codespaces
- multi-instance workflows
Expected UX: the VS Code extension UI would display a device-code URL + a short code, and poll until the user completes the flow in any browser. No local listener needed.
---
Optional improvements
- Avoid fixed port 1455 or ensure the actual selected port is always used in the redirect URL.
- Bind callback server to both IPv4 and IPv6 loopback (
127.0.0.1and::1). - Detect unreachable callback / state mismatch and proactively suggest Device Code sign-in.
---
Related
- [#5673 - cannot complete authentication with "sign in with chatgpt" option](https://github.com/openai/codex/issues/5673) - same class of problem (OAuth callback to
localhost:1455unreachable in Remote-SSH / WSL contexts), including a comment about multi-instance port conflicts and a maintainer suggesting the headless device login mechanism as a workaround. - Duplicates mentioned in #5673: #5668, #4265, #4230, #4034, #5283, #6403, #6616.
6 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Here's a screenshot from Feb 16 where I managed to complete the auth flow via curl from WSL (sensitive tokens redacted in red). This is the successful case, contrasting with the State mismatch I got on Feb 19 with multiple instances running.
<img width="1043" height="404" alt="Image" src="https://github.com/user-attachments/assets/4b5715e1-f870-4003-ae67-8ccde1ea7b9a" />
I just ran into this, it's hilariously stupid. I ended up doing a port proxy from port 1455 -> 1456 to let the auth flow work, then i deleted the proxy after oath succeeded.
So in summary:
I'm hitting a related issue on the Codex app for macOS:
If another local process (e.g. VSCode Code Helper) is already listening on port 1455,
the Codex client fails to start the login flow with "port already in use".
This occurs on macOS during a local Codex app login flow, even when the conflicting
listener is a local VSCode helper process used in a Remote SSH workflow (to a Raspberry Pi).
The conflict is entirely on the local machine (
127.0.0.1:1455).This suggests the fixed port assumption is fragile even in typical local development setups.
Workaround: closing VSCode frees the port and allows login to proceed.
This reinforces the need for:
Diagnostics:
lsof -i :1455shows Code Helper listening on127.0.0.1:1455I have multiple VMs, each on a new VSCode window and I'm trying to login to Codex on each VM. As user ViperG mentioned, VSCode auto assigns a different port if port 1455 is already in use (by another VM I signed into Codex earlier in my case). In this case, the sign in to codex is just "stuck" once I click "continue" after logging in on my browser and doesn't even give an error message. This shouldn't be hard to just figure out the correct port to redirect to, or as the issue says, allow user to copy the device code and paste if you can't figure this fix....
Still have the error.
I wanted to try Codex in a headless Linux sandbox. There are other options, I just didn't think I'd be an edge case in this instance. (Not using Windows.)