openai / openai/codex

codex mcp login ignores WWW-Authenticate resource_metadata during DCR discovery

Open
#42,427 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

auth bug CLI mcp
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

codex mcp login <server> --oauth-client-registration dcr does not follow the absolute resource_metadata URL advertised in the MCP server's 401 WWW-Authenticate challenge. Instead, it probes only .well-known metadata paths on the MCP resource origin. When those paths return 404, Codex falls back to dynamic registration on the MCP origin (/register) rather than discovering the distinct authorization server and its advertised registration_endpoint.

This breaks deployments where:

  • the MCP resource server and OAuth authorization server are different origins;
  • the resource server advertises protected-resource metadata through an absolute, centralized URL in WWW-Authenticate; and
  • the MCP resource origin intentionally does not serve .well-known/oauth-protected-resource itself.

Other MCP clients that follow the challenge's resource_metadata URL complete the flow.

Environment

  • Codex CLI 0.152.1 (rust-v0.152.1)
  • macOS arm64
  • codex mcp login oauth-repro --oauth-client-registration dcr

Minimal repro

The self-contained executable reproducer is in the first comment below. Save it as codex_mcp_oauth_dcr_repro.py and run:

python3 codex_mcp_oauth_dcr_repro.py

It starts three loopback-only servers:

  1. MCP resource server: /mcp returns 401 with an absolute resource_metadata URL.
  2. Central protected-resource-metadata server: returns an authorization_servers value pointing at server 3.
  3. OAuth authorization server: advertises /oauth2/register as its registration_endpoint.

The authorization server's DCR handler deliberately returns:

{"probe":"advertised-registration-endpoint"}

so a request reaching it is unambiguous and does not begin a browser OAuth flow.

Actual result from 0.152.1:

Error: Registration failed: Dynamic registration failed: Registration failed:
HTTP 404 Not Found: {"probe":"resource-not-found"}

The mock request log contains no request to the centralized PRM server and no request to the authorization server. It shows only requests to the MCP resource origin, followed by:

POST /register

Expected behavior

Codex should follow the absolute resource_metadata URL from the WWW-Authenticate challenge, fetch its authorization_servers metadata, then post the DCR request to the full registration_endpoint advertised by that authorization server.

Why this appears inconsistent with the current code

codex-rs/rmcp-client/src/oauth_client_registration.rs constructs an AuthorizationManager and calls resolve_metadata(). The same release's oauth_client_registration_tests.rs includes verified_issuer_can_delegate_authorization_and_token_to_one_origin, which verifies a DCR POST is sent to a delegated authorization-server endpoint.

The reproducer suggests the direct mcp login discovery path does not preserve or use the initial WWW-Authenticate challenge's resource_metadata URL when resolving metadata. That occurs before the delegated-registration test coverage.

Related issues

  • #34684: macOS Codex OAuth discovery failure while other MCP clients work on the same machine.
  • #20503: DCR interoperability issue involving registration metadata.

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.

Research direction

Start in codex-rs/rmcp-client/src/oauth_client_registration.rs, then read oauth_client_registration_tests.rs, especially verified_issuer_can_delegate_authorization_and_token_to_one_origin. Run the linked codex_mcp_oauth_dcr_repro.py reproducer and inspect discovery requests. Done means the absolute resource_metadata URL is followed and DCR reaches the advertised registration_endpoint.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, authentication
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.