[TT-17176] Mirror upstream PRM from the new oauth2.protectedResourceMetadata block#8297
Conversation
…etadata block The PRM auto-migration copies a mirror-shape MCP block (enabled, with no resource/authorizationServers) from the deprecated top-level authentication.protectedResourceMetadata into the new per-scheme oauth2.protectedResourceMetadata. The new block wins over the old one, but its serving path (serveOAuth2PRM) only assembled a static document — so a migrated mirror-mode MCP API served an empty static PRM doc instead of mirroring the upstream's, breaking transparent proxying of OAuth-protected remote MCP servers. Give OAuth2PRM the same IsMirrorMode semantics as the legacy type and dispatch to the shared mirror path when it applies. The suffix and AS-proxy routes already cover MCP APIs via GetPRMConfig's MCP default, so only the standard well-known endpoint needed the fix. Drop serveMirroredPRM's unused parameter while wiring the new caller. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
🚨 Jira Linter FailedCommit: The Jira linter failed to validate your PR. Please check the error details below: 🔍 Click to view error detailsNext Steps
This comment will be automatically deleted once the linter passes. |
|
This PR fixes a regression where OAuth2 Protected Resource Metadata (PRM) in "mirror mode" stopped working for Multi-Cloud Proxy (MCP) APIs after a recent configuration migration. Previously, an MCP API configured to mirror its upstream's PRM document started serving an empty static document instead. The fix re-introduces the mirror mode logic to the new Files Changed Analysis
Architecture & Impact AssessmentWhat this PR accomplishes: Key technical changes introduced:
Affected system components:
Request Flow for Mirrored PRM: sequenceDiagram
participant Client
participant Gateway
participant Upstream
Client->>Gateway: GET /.well-known/oauth-protected-resource
activate Gateway
Gateway->>Gateway: serveOAuth2PRM(prm)
Gateway->>Gateway: prm.IsMirrorMode(isMCP=true)?
Note over Gateway: Returns true
Gateway->>Gateway: serveMirroredPRM()
Gateway->>Upstream: GET /.well-known/oauth-protected-resource
activate Upstream
Upstream-->>Gateway: Upstream PRM Document
deactivate Upstream
Gateway->>Gateway: Rewrite 'resource' and 'authorization_servers'
Gateway-->>Client: 200 OK (Rewritten PRM Document)
deactivate Gateway
Scope Discovery & Context ExpansionThe changes are well-contained within the gateway's OAuth2 and PRM handling logic. The core impact is on the runtime behavior of MCP APIs using a specific authentication configuration.
Metadata
Powered by Visor from Probelabs Last updated: 2026-06-09T09:12:02.398Z | Triggered by: pr_opened | Commit: 1be609d 💡 TIP: You can chat with Visor using |
🎯 Recommended Merge TargetsBased on JIRA ticket TT-17176: Protected Resource Metadata — auto-migration of existing customers Fix Version: Tyk 5.14.0
Required:
📋 Workflow
|
✅ Architecture Check PassedNo architecture issues found – changes LGTM. ✅ Performance Check PassedNo performance issues found – changes LGTM. \n\n✅ Architecture Check PassedNo architecture issues found – changes LGTM. \n\n✅ Performance Check PassedNo performance issues found – changes LGTM. \n\n✅ Quality Check PassedNo quality issues found – changes LGTM. Powered by Visor from Probelabs Last updated: 2026-06-09T09:11:40.022Z | Triggered by: pr_opened | Commit: 1be609d 💡 TIP: You can chat with Visor using |
|



Summary
The PRM auto-migration (TT-17176) is non-destructive and copies the deprecated top-level
authentication.protectedResourceMetadatablock into the new per-schemeoauth2.protectedResourceMetadatalocation, where the new block wins over the old one at runtime.For an existing MCP API in mirror mode the legacy block is intentionally
{enabled: true}with noresource/authorizationServers— the shape the gateway treats as "mirror the upstream's PRM doc". After migration the gateway consults only the new block, but its serving path (serveOAuth2PRM) only ever assembled a static document. The result: a migrated mirror-mode MCP API served an empty static PRM doc (resource: "", noauthorization_servers) instead of mirroring the upstream — breaking transparent proxying of OAuth-protected remote MCP servers (mcp-remote / Claude Desktop discovery).Fix
OAuth2PRMthe sameIsMirrorMode(isMCP)semantics as the legacyProtectedResourceMetadatatype (enabled + no static fields + MCP → mirror).serveOAuth2PRMnow dispatches to the sharedserveMirroredPRMpath when the block resolves to mirror mode; static behavior is unchanged otherwise.GetPRMConfig's MCP default), so only the standard well-known endpoint needed the change.serveMirroredPRM's unused*oas.ProtectedResourceMetadataparameter.Tests
TestOAuth2PRM_MirrorMode(gateway): regression guard — a mirror-shape MCP API on the new block must serve the mirrored upstream doc (rewrittenresource,authorization_serverspointing at the Tyk AS proxy, upstream pass-through fields), not an empty static doc. Verified RED before the fix, GREEN after.TestOAuth2PRM_IsMirrorMode(apidef/oas): table-driven unit coverage of the new method, mirroring the legacy type's test.🤖 Generated with Claude Code