`codex mcp login` fails with "No authorization support detected" on macOS against a spec-compliant OAuth server (same version works on Linux)

Open
#34,684 10 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
macos, rust

Research direction

Start with the macOS login path and the discovery handling that produces No authorization support detected, comparing it with the Linux flow and the successful metadata requests described here. Then inspect codex-rs/rmcp-client/src/perform_oauth_login.rs, especially OauthCallbackResult and callback handling, alongside the rmcp 1.8.0 behavior. Done means OAuth discovery proceeds on macOS with a useful failure if it cannot, and the callback preserves RFC 9207 iss.

Written by the indexing model from the issue text.

Description

bug CLI mcp

Summary

codex mcp login <server> fails instantly with Error: No authorization support detected
on macOS (arm64) against a fully spec-compliant OAuth 2.0 authorization server.
The same codex version completes the entire flow on Linux against the same server
(discovery → dynamic client registration → browser → token). Other MCP clients
(Claude Code, mcp-remote) complete OAuth against this server without issues —
including mcp-remote running on the same Mac, which rules out the machine's
network/TLS stack and the server itself.

A second, independent defect (RFC 9207 iss dropped when relaying the OAuth callback)
was found while debugging; see the last section. Happy to split it into its own issue.

Environment

  • codex-cli 0.144.6 (pins rmcp 1.8.0 per codex-rs/Cargo.lock of tag rust-v0.144.6)
  • macOS: 26.5.2, BuildVersion 25F84; uname -m = arm64 (Mac mini)
  • Install: official binary at ~/.local/bin/codex; also reproduced with the pristine
    release tarball
    codex-aarch64-apple-darwin.tar.gz from the rust-v0.144.6 GitHub
    release, executed directly
  • No proxies: env | grep -i proxy is empty; scutil --proxy shows only the default
    ExceptionsList (*.local, 169.254/16), no HTTP/HTTPS/SOCKS/PAC
  • Reproduced with a fresh CODEX_HOME (empty directory), so user config is not involved
  • RUST_LOG=debug codex mcp login <server> prints nothing beyond the error itself

Repro steps (macOS)

mkdir -p ~/codex-test && cd ~/codex-test
curl -LO https://github.com/openai/codex/releases/download/rust-v0.144.6/codex-aarch64-apple-darwin.tar.gz
tar xzf codex-aarch64-apple-darwin.tar.gz
mkdir home && export CODEX_HOME=~/codex-test/home
./codex-aarch64-apple-darwin mcp add sparrow --url https://mcp.example.com/mcp
# → Added global MCP server 'sparrow'.
# → Detected OAuth support. Starting OAuth flow…
# → Error: No authorization support detected
./codex-aarch64-apple-darwin mcp login sparrow
# → Error: No authorization support detected

(Hostname sanitized throughout: mcp.example.com = a self-hosted MCP server behind
nginx with a valid Let's Encrypt certificate, reachable over the public internet.)

Server capabilities

Self-hosted MCP server (Streamable HTTP) whose app is its own OAuth 2.0 authorization
server (OpenIddict 7.5):

  • 401 on /mcp with
    WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"
  • RFC 9728 protected resource metadata at the root path and the path-suffixed variant
    (/.well-known/oauth-protected-resource/mcp)
  • RFC 8414 AS metadata at /.well-known/oauth-authorization-server (root and
    path-suffixed), plus /.well-known/openid-configuration
  • RFC 7591 dynamic client registration (registration_endpoint advertised; returns 201
    with a public PKCE client, token_endpoint_auth_method=none)
  • token_endpoint_auth_methods_supported includes "none"
  • authorization_servers[0] matches the AS issuer byte-for-byte (trailing slash included)
  • Authorization Code + PKCE (S256); response_types_supported: ["code"]

What the server sees during a failing macOS codex mcp login (nginx access log)

CLIENT_IP - - [20/Jul/2026:18:30:56 +0000] "GET /mcp HTTP/1.1" 401 0 "-" "-"
CLIENT_IP - - [20/Jul/2026:18:30:56 +0000] "GET /.well-known/oauth-protected-resource HTTP/1.1" 200 218 "-" "-"
CLIENT_IP - - [20/Jul/2026:18:30:56 +0000] "GET /.well-known/oauth-authorization-server HTTP/1.1" 200 1653 "-" "-"

All three requests succeed — then nothing. No fallback attempt to
/.well-known/openid-configuration, no POST to the registration endpoint. The CLI
prints Error: No authorization support detected immediately.

This should be impossible if the 200 AS-metadata response was actually processed:
rmcp 1.8.0's discover_metadata() returns NoAuthorizationSupport only after all
discovery candidates fail, and a successful parse of that document would have continued
to DCR (as it does on Linux, below). This suggests the login path's HTTP client fails
client-side on macOS, separately from the requests above.

Same binary version on Linux (x86_64) — full success

CLIENT_IP - - [20/Jul/2026:18:02:01 +0000] "POST /oauth/register HTTP/1.1" 201 261 "-" "-"
CLIENT_IP - - [20/Jul/2026:18:02:01 +0000] "GET /oauth/authorize?response_type=code&client_id=…&code_challenge=…&code_challenge_method=S256&redirect_uri=http%3A%2F%2F127.0.0.1%3A33721%2Fcallback%2F…&scope=openid+offline_access+mcp&resource=https%3A%2F%2Fmcp.example.com%2Fmcp HTTP/2.0" 302 0

codex mcp login output on Linux (after the RFC 9207 server-side workaround described
below): Successfully logged in to MCP server 'sparrow'.codex mcp list shows
Status enabled / Auth OAuth.

mcp-remote from the SAME Mac — full success

CLIENT_IP - - [20/Jul/2026:18:58:26 +0000] "GET /oauth/authorize?…" 302 … "node"
CLIENT_IP - - [20/Jul/2026:18:58:26 +0000] "GET /.well-known/oauth-protected-resource/mcp HTTP/1.1" 200 218 "-" "node"
CLIENT_IP - - [20/Jul/2026:18:58:26 +0000] "POST /oauth/token HTTP/1.1" 200 4575 "-" "node"
CLIENT_IP - - [20/Jul/2026:18:58:26 +0000] "POST /mcp HTTP/1.1" 200 77092 "-" "node"   ← tools/list

Same machine, same network, same server: the stdio bridge (codex mcp add sparrow -- npx -y mcp-remote https://mcp.example.com/mcp) completes OAuth and lists tools. This is
our current workaround.

Live metadata documents (sanitized)

GET /.well-known/oauth-protected-resource → 200:

{"resource":"https://mcp.example.com/mcp","authorization_servers":["https://mcp.example.com/"],"scopes_supported":["mcp","offline_access"],"bearer_methods_supported":["header"]}

GET /.well-known/oauth-authorization-server → 200 (identical at
/.well-known/openid-configuration and both path-suffixed variants):

{
  "issuer": "https://mcp.example.com/",
  "authorization_endpoint": "https://mcp.example.com/oauth/authorize",
  "token_endpoint": "https://mcp.example.com/oauth/token",
  "revocation_endpoint": "https://mcp.example.com/oauth/revoke",
  "jwks_uri": "https://mcp.example.com/.well-known/jwks",
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "response_types_supported": ["code"],
  "response_modes_supported": ["query", "form_post", "fragment"],
  "scopes_supported": ["openid", "offline_access", "mcp"],
  "claims_supported": ["aud", "exp", "iat", "iss", "sub"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "code_challenge_methods_supported": ["plain", "S256"],
  "subject_types_supported": ["public"],
  "prompt_values_supported": ["consent", "login", "none", "select_account"],
  "token_endpoint_auth_methods_supported": ["none", "client_secret_basic", "client_secret_post", "private_key_jwt"],
  "revocation_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"],
  "require_pushed_authorization_requests": false,
  "tls_client_certificate_bound_access_tokens": false,
  "registration_endpoint": "https://mcp.example.com/oauth/register",
  "claims_parameter_supported": false,
  "request_parameter_supported": false,
  "request_uri_parameter_supported": false,
  "authorization_response_iss_parameter_supported": false,
  "authorization_response_iss_parameter_supported_NOTE": "false is a WORKAROUND for the second bug below; the server actually sends iss. It was true when that bug reproduced."
}

(The _NOTE key is annotation for this issue, not part of the live document.)

Second defect: RFC 9207 iss is dropped when relaying the OAuth callback

Found while debugging on Linux, where the flow gets further. With
authorization_response_iss_parameter_supported: true advertised (the honest value),
codex mcp login on Linux failed at the callback stage:

Error: failed to handle OAuth callback

Caused by:
    Authorization server response missing required issuer: expected https://mcp.example.com/

Evidence the server sends iss correctly — raw callback captured with a local listener
(DCR probe client, browser completed the redirect):

GET /cb?code=…&state=…&iss=https%3A%2F%2Fmcp.example.com%2F HTTP/1.1

Byte-exact match with the advertised issuer. Cause, from the codex source
(codex-rs/rmcp-client/src/perform_oauth_login.rs): the local callback server extracts
only code and state (OauthCallbackResult { code, state }) and calls
oauth_state.handle_callback(&code, &csrf_state) — the variant without issuer.
rmcp 1.8.0 (validate_authorization_response_issuer) then requires iss because the
AS metadata advertises support → guaranteed failure against any server that honestly
advertises RFC 9207. Codex discards the very parameter rmcp then demands.

Suggested fix: extract iss from the callback query and use
handle_callback_with_issuer / handle_callback_url.

Current server-side workaround (required for codex to work at all): advertise
authorization_response_iss_parameter_supported: false while still sending iss.

Expected behavior

  1. macOS: the OAuth flow proceeds as it does on Linux — or the error names the actual
    failing step instead of No authorization support detected after three successful
    discovery responses.
  2. The callback relay preserves iss so servers can honestly advertise RFC 9207.
Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.