Skip to content

[TT-17176] Mirror upstream PRM from the new oauth2.protectedResourceMetadata block#8297

Merged
lghiur merged 1 commit into
masterfrom
TT-17176-prm-new-block-mirror-mode
Jun 9, 2026
Merged

[TT-17176] Mirror upstream PRM from the new oauth2.protectedResourceMetadata block#8297
lghiur merged 1 commit into
masterfrom
TT-17176-prm-new-block-mirror-mode

Conversation

@lghiur

@lghiur lghiur commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

The PRM auto-migration (TT-17176) is non-destructive and copies the deprecated top-level authentication.protectedResourceMetadata block into the new per-scheme oauth2.protectedResourceMetadata location, 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 no resource/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: "", no authorization_servers) instead of mirroring the upstream — breaking transparent proxying of OAuth-protected remote MCP servers (mcp-remote / Claude Desktop discovery).

Fix

  • Give OAuth2PRM the same IsMirrorMode(isMCP) semantics as the legacy ProtectedResourceMetadata type (enabled + no static fields + MCP → mirror).
  • serveOAuth2PRM now dispatches to the shared serveMirroredPRM path when the block resolves to mirror mode; static behavior is unchanged otherwise.
  • The path-suffix and AS-proxy routes already cover MCP APIs (via GetPRMConfig's MCP default), so only the standard well-known endpoint needed the change.
  • Dropped serveMirroredPRM's unused *oas.ProtectedResourceMetadata parameter.

Tests

  • TestOAuth2PRM_MirrorMode (gateway): regression guard — a mirror-shape MCP API on the new block must serve the mirrored upstream doc (rewritten resource, authorization_servers pointing 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

…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]>
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🚨 Jira Linter Failed

Commit: 1be609d
Failed at: 2026-06-09 09:10:29 UTC

The Jira linter failed to validate your PR. Please check the error details below:

🔍 Click to view error details
failed to get Jira issue: failed to fetch Jira issue TT-17176: Issue does not exist or you do not have permission to see it.: request failed. Please analyze the request body for more details. Status code: 404

Next Steps

  • Ensure your branch name contains a valid Jira ticket ID (e.g., ABC-123)
  • Verify your PR title matches the branch's Jira ticket ID
  • Check that the Jira ticket exists and is accessible

This comment will be automatically deleted once the linter passes.

@probelabs

probelabs Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

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 oauth2.protectedResourceMetadata configuration block, ensuring it behaves identically to the deprecated top-level block it replaced. The PRM serving endpoint now correctly detects this mode and dispatches to the existing mirroring implementation, restoring the transparent proxying of OAuth-protected upstream services.

Files Changed Analysis

  • apidef/oas/oauth2.go: Adds the IsMirrorMode method to the OAuth2PRM struct to replicate the mirror mode detection logic from the old configuration block.
  • apidef/oas/oauth2_test.go: Adds a unit test (TestOAuth2PRM_IsMirrorMode) to verify the correctness of the new IsMirrorMode method.
  • gateway/mw_protected_resource.go: This is the core of the fix. The serveOAuth2PRM function is updated to check IsMirrorMode and call serveMirroredPRM when active. The signature for serveMirroredPRM was also simplified by removing an unused parameter.
  • gateway/api_loader.go: Updates a call to serveMirroredPRM to match its new, simplified signature.
  • gateway/mw_protected_resource_test.go: Adds a crucial regression test (TestOAuth2PRM_MirrorMode) that simulates a request to a migrated MCP API in mirror mode, asserting that it correctly serves the rewritten upstream PRM document.

Architecture & Impact Assessment

What this PR accomplishes:
This PR restores critical functionality for MCP APIs that rely on PRM mirroring. It fixes a regression introduced during the auto-migration of the authentication.protectedResourceMetadata configuration, ensuring that migrated APIs continue to proxy their upstream's PRM document correctly.

Key technical changes introduced:

  1. The apidef/oas.OAuth2PRM struct now has an IsMirrorMode(isMCP bool) method, making its behavior consistent with the legacy PRM configuration.
  2. The gateway's PRM middleware (serveOAuth2PRM) now dispatches to the serveMirroredPRM handler for configurations that resolve to mirror mode.
  3. The signature of serveMirroredPRM has been cleaned up by removing a redundant parameter.

Affected system components:

  • API Gateway: The request handling logic for OAuth2 Protected Resource Metadata is directly affected.
  • API Definition (OAS): The interpretation of the oauth2.protectedResourceMetadata extension is modified to support mirror mode.
  • Multi-Cloud Proxy (MCP): The fix directly impacts MCP APIs that proxy OAuth-protected upstream services, which is the primary use case for PRM mirror mode.

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
Loading

Scope Discovery & Context Expansion

The 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.

  • The modification in gateway/mw_protected_resource.go is central, altering the request flow for the PRM well-known endpoint (/.well-known/oauth-protected-resource).
  • The change in apidef/oas/oauth2.go affects how API definitions are parsed and interpreted by the gateway loader, specifically for determining PRM behavior.
  • The regression test added in gateway/mw_protected_resource_test.go is critical as it validates the end-to-end flow, from API loading to the final HTTP response, preventing future regressions of this specific behavior.
  • This fix is a direct consequence of a previous migration feature (TT-17176), highlighting the importance of testing all operational modes (like mirror mode) after configuration schema changes.
Metadata
  • Review Effort: 2 / 5
  • Primary Label: bug

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 /visor ask <your question>

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🎯 Recommended Merge Targets

Based on JIRA ticket TT-17176: Protected Resource Metadata — auto-migration of existing customers

Fix Version: Tyk 5.14.0

⚠️ Warning: Expected release branches not found in repository

Required:

  • master - No matching release branches found. Fix will be included in future releases.

📋 Workflow

  1. Merge this PR to master first

@probelabs

probelabs Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

✅ Architecture Check Passed

No architecture issues found – changes LGTM.

✅ Performance Check Passed

No performance issues found – changes LGTM.

\n\n

✅ Architecture Check Passed

No architecture issues found – changes LGTM.

\n\n

✅ Performance Check Passed

No performance issues found – changes LGTM.

\n\n

✅ Quality Check Passed

No 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 /visor ask <your question>

@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
81.2% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

@lghiur
lghiur merged commit 2191c98 into master Jun 9, 2026
53 of 55 checks passed
@lghiur
lghiur deleted the TT-17176-prm-new-block-mirror-mode branch June 9, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants