Skip to content

fix(server): allow exact MCP OAuth resource aliases - #23806

Open
freeman-dcarr wants to merge 4 commits into
pingdotgg:mainfrom
freeman-dcarr:fix/mcp-oauth-resource-aliases
Open

freeman-dcarr wants to merge 4 commits into
pingdotgg:mainfrom
freeman-dcarr:fix/mcp-oauth-resource-aliases

Conversation

@freeman-dcarr

@freeman-dcarr freeman-dcarr commented Oct 22, 2026 •

Copy link
Copy Markdown

Problem

A hosted MCP client can discover and register with T3 through an OpenAI secure MCP tunnel, but the tunnel can advertise its own resource URL, such as /v1/mcp/<id>. The client sends that resource to /oauth/mcp/authorize; T3 accepts only its native ${origin}/mcp resource and returns invalid_target before token issuance. This is an observed resource-validation failure, not a demonstrated token-audience rejection.

Change

Adds T3CODE_MCP_RESOURCE_ALIASES, a comma-separated list of trusted alternative resource URLs for the same environment. Unset configuration retains the existing behavior.

  • Configured aliases match exactly. Each entry must be a canonical HTTPS URL without credentials, a query or a fragment; invalid configuration fails startup without echoing the entry.
  • The accepted resource is bound to the authorization code. Token exchange must present the same resource or omit it; a mismatch spends the code.
  • One-click approval CSRF tokens also cover the selected resource.
  • Native resource matching and request-derived discovery/issuer URLs retain their existing behavior. MCP sessions remain environment-wide rather than audience-scoped.
  • The guide explains how to copy and URL-decode the actual authorization resource parameter, browser reachability of the advertised authorization server, configuration rollback, existing-session revocation, and the public authenticated route retained when T3 Connect remains enabled alongside a private tunnel.

Aliases only make a rewritten OAuth resource acceptable; they do not provide a general tunnel router or make an unreachable authorization-server address reachable.

Base and head

  • Target: main, snapshot fetched at 2026-10-26 15:18:05 UTC.
  • Base: 3f9448747bb8848050dc2cacf83affa6f94a66a1.
  • Head: d085a93a02282cc247db8b2f34a9b5a2f213d120.

The three original patch commits retain identical patch IDs after rebasing. The follow-up adds regression coverage and documentation; the final documentation clarification does not change server code or tests.

Validation

Run in an isolated Windows x64 checkout with Node 26.12.1, pnpm 12.14.0, Vite+ 1.4.0, and a frozen-lockfile dependency installation with lifecycle scripts disabled. No installed T3 instance or live profile was used.

  • vp test run apps/server/src/auth/McpOAuth.test.ts apps/server/src/cli/config.test.ts: 26 tests passed in 2 files, including native sign-in with aliases configured, exact alias refusals, code/resource binding and single use, cross-origin alias exchange within the same environment, native-origin mismatch refusal, approval CSRF binding, discovery/callback issuer consistency, and alias configuration validation.
  • Format check on all six changed files and lint on all five changed TypeScript files: passed.
  • Typecheck of both affected packages, t3 and @t3tools/scripts: passed.
  • Server generated GraphQL operations check: passed.
  • Both knip:check passes: passed.
  • git diff --check: passed.

Negative controls ran in a separate isolated checkout with the candidate tests:

  • Restoring the pinned upstream McpOAuth.ts makes the alias regression fail at invalid_target instead of the expected approval handoff.
  • Removing only the resource from the approval CSRF input makes the resource-replay regression fail: it receives HTTP 200 where HTTP 400 is required.

The check:changed wrapper was attempted but stopped during prolonged Git input enumeration, before its checks ran. The selected constituent checks listed above were run directly; this is not a claim that the wrapper completed.

Not run: full test suites, full build, or a deployed end-to-end ChatGPT/OpenAI-tunnel sign-in. No deployment was performed. Live sign-in still requires the browser to reach the advertised authorization-server address.

Scope

This is a focused configuration option for the established hosted-agent MCP OAuth capability (#16336, #16718). It changes which exact resource URLs an operator may explicitly trust for that environment, without a new workflow or changed default. No prior issue or discussion preceded this PR; this is the rationale under the focused configuration exception.

Original implementation: Claude Opus 5.5 in Claude Code. Rebase, regression coverage and documentation updates: GPT-6 in Codex, with Claude adversarial review.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 22, 2026
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 79c1166 and d085a93.

Files selected for processing: 6
  • apps/server/src/auth/McpOAuth.test.ts
  • apps/server/src/auth/McpOAuth.ts
  • apps/server/src/cli/config.test.ts
  • apps/server/src/cli/config.ts
  • apps/server/src/config.ts
  • docs/user/outside-agents.md

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The server configuration now accepts canonical HTTPS MCP resource aliases. OAuth authorization can bind a request to an exact configured alias, and token exchange validates the requested resource against the resource stored with the authorization code.

Changes: MCP resource alias authorization

Layer / File(s) Summary
Alias configuration and validation
apps/server/src/config.ts, apps/server/src/cli/config.ts, apps/server/src/cli/config.test.ts
ServerConfig adds mcpResourceAliases. The environment parser reads comma-separated values, trims entries, omits empty entries, and rejects URLs that do not meet the canonical HTTPS requirements. Tests cover parsing and rejection cases.
OAuth authorization and token exchange
apps/server/src/auth/McpOAuth.ts, apps/server/src/auth/McpOAuth.test.ts, docs/user/outside-agents.md
OAuth authorization accepts an exact configured alias and stores the resolved resource. Token exchange defaults an omitted resource to the stored resource and requires a match. Tests cover alias authorization, resource mismatches, spent codes, discovery metadata, and browser-session approval. The setup instructions describe configuring secure MCP tunnel URLs.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant McpOAuth
  participant ServerConfig
  MCPClient->>McpOAuth: Send authorization request with resource
  McpOAuth->>ServerConfig: Read mcpResourceAliases
  ServerConfig-->>McpOAuth: Return configured aliases
  McpOAuth-->>MCPClient: Return authorization code bound to resolved resource
  MCPClient->>McpOAuth: Send token request with code and optional resource
  McpOAuth-->>MCPClient: Return token when the resolved resource matches the code resource
Loading

Possibly related PRs

  • pingdotgg/t3code#18417: Both changes affect MCP approval decisions and retry behavior for the same approval code.

Suggested reviewers: juliusmarminge

Merge Risk: Minimal · up to d085a

No merge-blocking issue was established. The configured aliases remain intended for addresses that reach the same environment.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title "fix(server): allow exact MCP OAuth resource aliases" follows conventional commit form and names the main change: a configurable exact-match alias list for MCP OAuth resource validation. The…
Description check Passed The description follows the repository template. It has Problem, Change, Scope and approval, and Verification sections. The Problem section explains the failure with the tunnel resource and the invali…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "fix(server): allow exact MCP OAuth resource aliases" follows conventional commit form and names the main change: a configurable exact-match alias list for MCP OAuth resource validation. The changeset adds T3CODE_MCP_RESOURCE_ALIASES parsing, alias matching in McpOAuth.ts, resource binding on authorization codes and CSRF tokens, and related tests and docs. The PR objectives describe the same change, so the title is fully related to the main change.

Full details: Description check

Explanation

The description follows the repository template. It has Problem, Change, Scope and approval, and Verification sections. The Problem section explains the failure with the tunnel resource and the invalid_target response. The Change section describes the new option, exact matching, code and CSRF binding, and the docs. The Scope section cites the focused-configuration exception and explains why no prior issue exists. The Verification section lists the tests run, results, negative controls, and items not run. The description is thorough and specific, so it is mostly complete.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@freeman-dcarr
freeman-dcarr force-pushed the fix/mcp-oauth-resource-aliases branch from 4c7beb6 to 79c1166 Compare October 23, 2026 13:03
freeman-dcarr and others added 4 commits October 26, 2026 11:18
…unnel

An OpenAI secure MCP tunnel rewrites protected-resource metadata to its own
address, and ChatGPT sends that address as the RFC 8707 resource on both the
authorization and token requests, so T3 refused every sign-in with
invalid_target. T3CODE_MCP_RESOURCE_ALIASES lists exact https URLs that MCP
OAuth also issues tokens for. The accepted resource is bound to the
authorization code and must match at token exchange. Nothing changes when
the variable is unset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With resource aliases, the same session, client, redirect and PKCE challenge
can be approved for more than one resource, so the approval CSRF token now
covers the resource too. The user guide notes that removing an alias does not
end sign-ins already approved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@freeman-dcarr
freeman-dcarr force-pushed the fix/mcp-oauth-resource-aliases branch from 79c1166 to d085a93 Compare October 26, 2026 15:27
@freeman-dcarr freeman-dcarr changed the title fix(server): ChatGPT can sign in to T3 through an OpenAI secure MCP tunnel fix(server): allow exact MCP OAuth resource aliases Oct 26, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant