Support remote / headless OAuth sign-in
Feature Request: Support “remote/headless” OAuth sign-in (copy-paste auth code flow, no localhost callback)
TL;DR
When using Codex from a remote/headless environment (e.g., VS Code Server/Code-Server inside Docker on a VPS), the current login flow attempts to open a browser and uses a http://localhost:<port>/auth/callback redirect. This is impossible to complete from a terminal-only session. Please add a hosted redirect + copy-paste code sign-in path (PKCE), similar to what other CLIs do, so users can copy a short code from a web page back into the CLI. Also add flags/env vars to fully disable the localhost callback server.
Motivation
-
Scenario: Running Codex in a terminal inside code-server (VS Code in browser) within a Docker container on a VPS.
-
Problem: The CLI prints:
Welcome to Codex, OpenAI's command-line coding agent Finish signing in via your browser If the link doesn't open automatically, open the following link to authenticate: https://auth.openai.com/oauth/authorize?...&redirect_uri=http%3A%2F%2Flocalhost%3A1455%2Fauth%2Fcallback... Press Esc to cancelBecause the redirect is to
localhost:<port>, the OAuth callback cannot reach the CLI (there’s no local browser/network path to that localhost). Result: sign-in is impossible in common remote setups (SSH, tmux, containers, CI runners, devboxes, codespaces/code-server, etc.). -
What’s needed: A headless-friendly sign-in flow that:
- Prints a URL the user can open on any machine,
- Shows a short one-time code on the hosted page after auth,
- Lets the user paste that code back into the CLI to finish sign-in.
This avoids any localhost callback and unblocks remote workflows.
Proposed Solution (globally same as claude)
Add “Hosted Redirect + Copy-Paste Code” Flow (PKCE)
- CLI launches OAuth with PKCE and
redirect_uripointing to an OpenAI-hosted page (e.g.,https://console.openai.com/cli/callback). - After the user signs in (in any browser), the hosted page displays a short one-time code (e.g.,
ABCD-EFGH-IJKL) tied to the CLI session viastate. - The CLI prompts:
Paste the authentication code:and exchanges it (withcode_verifier) for tokens. - The CLI never depends on a local HTTP server.
Benefits
- Works over SSH, in containers, CI, WSL, headless nodes, and code-server.
- No need for port forwarding or opening localhost in the server environment.
- Familiar UX users already see in other CLIs.
UX / CLI Flow (Example)
CLI (headless mode detected or --no-localhost):
> codex login
Opening a browser is disabled. To sign in:
1) Visit this URL in any browser:
https://auth.openai.com/oauth/authorize?...&no-redirect_uri=true%2Fcli%2Fcallback&code_challenge=...
2) Complete sign-in. You’ll see a one-time Authentication Code.
3) Paste the code here:
> █
Why This Matters
Remote and headless development is now the norm (SSH, containers, devboxes, code-server, codespaces). A localhost-only OAuth callback blocks a large portion of real-world setups. A copy-paste code flow removes friction and aligns Codex with modern CLI auth UX.
Thanks! This change would make Codex much easier to adopt in enterprise and cloud-native workflows while keeping security tight.
Are you interested in implementing this feature?
No response
Additional information
No response
Workaround is to login locally and copy paste the auth.json file to the remote instance.
Another workaround is to copy as curl the failing callback and run it on the headless machine
I bought plus to try codex. I mainly use claude-code but tinker with gemini-cli and qwen coder, they all support this workflow. Cancelled my account because it's insufficiently convenient to use codex in a container (I'm not running it outside of one).
I was actually willing to curl the redirected url as @orysonc suggested but NB you really need copy as curl eg. from dev tools to grab the headers too; the GET parameters are insufficient. Too much of a hassle to be a sustainable workaround for me.
Workaround: Complete Codex OAuth from a remote/headless machine using Firefox → “Copy as cURL (POSIX)”
Scenario Codex CLI (codex login) runs on a remote box (VM/LXC/SSH/CI). Your browser is on a different machine. The login flow redirects to http://localhost:1455/auth/callback?..., which fails locally. This workaround replays that failing browser redirect on the remote host by copying it as a full curl request (including headers).
Prereqs
Shell access to the machine where Codex runs.
Firefox on your local desktop.
Steps (copy-paste ready)
Start the login server on the remote host (Shell A) codex:
codex login
>_ Welcome to Codex, OpenAI's command-line coding agent > Finish signing in via your browser If the link doesn't open automatically, open the following link to authenticate:
https://auth.openai.com/oauth/authorize?response_type=code&client_id=app_EMoamEEZ73f0CkXaXp7hran..........
# Leave this running at "Press Esc to cancel"
On your desktop (Firefox): open the Auth URL printed by codex login, sign in. You’ll land on a page that fails to reach http://localhost:1455/... — that’s expected.
Open Firefox DevTools → Network:
Press F12, switch to Network.
(Optional) enable Persist logs.
Re-trigger the failing redirect (click “Try again” or paste the full callback URL in the address bar and hit Enter).
Copy the failing request as cURL (POSIX):
In the Network list, right-click the GET …/auth/callback?... entry → Copy → Copy as cURL (POSIX). (Do not choose “Windows”; do not copy just the URL.)
Back on the remote host (Shell B or screen, same machine as Shell A):
While codex login is still waiting, paste & run the copied curl command:
Example shape – yours will be longer and include headers:
curl 'http://localhost:1455/auth/callback?code=...&scope=...&state=...'
-H 'User-Agent: Mozilla/5.0 ...'
-H 'Accept: /'
--compressed
Confirm success (Shell A): codex login should finish with a “signed in” message. From now on, just run:
or Close /Break login process and restart codex , dont worry , OAuth is done:)
codex
Gotchas & Troubleshooting
Short-lived codes: If you see HTTP 400 State mismatch, start a fresh login:
Shell A
codex login
Then repeat Steps 2–5 with the new callback request.
Server must be listening: The callback server only exists while codex login runs.
ss -tlnp | grep 1455 || netstat -tlnp | grep 1455
Expect LISTEN on 127.0.0.1:1455 on the remote host
Connection refused → restart codex login, then re-run the cURL.
Use POSIX variant: “Copy as cURL (POSIX)” works on Linux containers. The Windows cURL format won’t run cleanly on Linux.
Don’t strip quotes/line breaks: Paste the command exactly as copied. If it spans multiple lines with , keep them.
Security: The callback URL contains a short-lived auth code. Treat it as sensitive; don’t share it.
Thanks for the copy auth.json workaround, it does work
I still think the CLI should support the headless OAuth flow I described. Tools like Claude Code or Gemini CLI already provide this, and it makes connecting much easier in shell-only or remote sessions without having to copy files around.
This really needs to be implemented natively. Claude Code and Gemini do it very simply, a link, go to it and auth, and that process seems to talk directly w/ anthropic/google servers to verify auth. Clean and works every time.
With codex, I've tried using an SSH tunnel and I get back an error, "ERR_EMPTY_RESPONSE", so it's getting through, but not working.
No matter what I do, or how quickly I run through the steps, all I get from the curl command is: Token exchange failed: token endpoint returned status 400 Bad Request
Another workaround is to port forward 1455:localhost:1455 . Use codex login command on the remote server. Was able to paste the Auth URL on my local browser and the redirect worked correctly and logged me in.
Another workaround is to port forward 1455:localhost:1455 . Use codex login command on the remote server. Was able to paste the Auth URL on my local browser and the redirect worked correctly and logged me in.
ssh -L 1455:localhost:1455 youruser@your-linux-box-ip
for anyone needing the syntax for trying to access headless Linux from Windows.
I agree that this should be implemented. All these workarounds... looks like claude created them :)
No matter what I do, or how quickly I run through the steps, all I get from the curl command is: Token exchange failed: token endpoint returned status 400 Bad Request
I just went through the Firefox workaround - you really do have to use Firefox (or at least it happens to structure the CURL command correctly). I tried doing the same thing from the Brave browser and would get the 400 Bad Request error. Completely restarting the process seemed to work. I got no confirmation on the codex side ("Terminal A") that it worked, had to CTRL+C from codex login and just relaunch codex. /status confirmed that I am signed in to my Pro account.
yay, looks someone implemented a better auth method, hopefully it will be merged soon.
The fix with firefox worked for me. It has already been mentioned upward but mostly for future reference, make sure to use the copy as cURL(POSIX).
There are workarounds, but relying on workarounds for a feature that should've been there on day 1 isn't great UX. The current auth flow isn't great, and the fact that I don't have this issue with competing products is pretty telling.
Workaround from @tedmarcin works on brave too (so should be working with other chromium based web browsers)
all I get from the curl firefox is Token exchange failed: token endpoint returned status 400 Bad Request too,
But the copy the auth.json works flawlessly and its easier
Setting networkingMode=VirtioProxy in .wslconfig allows the localhost callback to work. You will have to manually copy-paste the initial auth URL into your browser though.
it works fine for me if I open the 1455 port when running my docker container, just route it via ipv4 you dont need headless login, it would be nice, but routing the port to the host where you have a browser works fine
fully headless applications - yes still needs a fix
Thanks for the help, I was able to Oauth codex login, in my docker container, sequence was not the same in the guides people have posted here but it was helpful enough to figure it out, I had a certain window before it times out only a few seconds, I had to be quick to right click on the callback and paste it into my shell terminal.
@MFS2020
it works fine for me if I open the 1455 port when running my docker container, just route it via ipv4 you dont need headless login, it would be nice, but routing the port to the host where you have a browser works fine
fully headless applications - yes still needs a fix
Could you explain this in more detail
@dimascior
Thanks for the help, I was able to Oauth codex login, in my docker container, sequence was not the same in the guides people have posted here but it was helpful enough to figure it out, I had a certain window before it times out only a few seconds, I had to be quick to right click on the callback and paste it into my shell terminal.
I started randomly getting this error
⚠️ stream error: exceeded retry limit, last status: 401 Unauthorized, request id: 98c4f1xxxxxxxx7b-EWR; retrying 1/5 in 212ms…
it basically lost my authentication which i had for a week, i am trying to replicate what i did and it is not working even with ipv4. @a428tm dimascior holds the key now lol, I am trying to figure it out if i do ill get back and share, this is so annoying...
Thanks for the help, I was able to Oauth codex login, in my docker container, sequence was not the same in the guides people have posted here but it was helpful enough to figure it out, I had a certain window before it times out only a few seconds, I had to be quick to right click on the callback and paste it into my shell terminal.
I started randomly getting this error
⚠️ stream error: exceeded retry limit, last status: 401 Unauthorized, request id: 98c4f1xxxxxxxx7b-EWR; retrying 1/5 in 212ms…it basically lost my authentication which i had for a week, i am trying to replicate what i did and it is not working even with ipv4. @a428tm dimascior holds the key now lol, I am trying to figure it out if i do ill get back and share, this is so annoying...
exact same problem here
@myudak the only conclusion I can make is that they really don't want their codex to be used inside containers, because they identify those as actual pro environments, so they clock you out and expire your token, ill keep my eye on this, but this happens in the most inconvenient times...
It seems the new auth method still hasn't been released so I'm again trying to use the ssh tunnel.
I have it all setup, I've verified w/ netstat on the windows side, linux server I'm ssh'ed into AND in the docker container I'm using. All looks good as far as ports, etc.
I when I click through after putting the browser link in chrome, I get this:
This page isn’t working localhost didn’t send any data. ERR_EMPTY_RESPONSE
Anything I can do to troubleshoot the codex side? I've tried both codex login and doing a login from the console UI.
Workaround is to login locally and copy paste the auth.json file to the remote instance.
By the way, auth.json is under ~/.codex
Workaround is to login locally and copy paste the auth.json file to the remote instance.
By the way, auth.json is under
~/.codex
reusing auth.json from another machine often ends up with this error:
■ Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
I just hit this myself, so I'm bumping the conversation. This is not fixed in codex-cli 0.58.0