Skip to content

fix: rewrite auth server URLs for remote deployments#99

Open
salmon-21 wants to merge 2 commits intohyprmcp:mainfrom
salmon-21:fix/remote-auth-server-url-rewriting
Open

fix: rewrite auth server URLs for remote deployments#99
salmon-21 wants to merge 2 commits intohyprmcp:mainfrom
salmon-21:fix/remote-auth-server-url-rewriting

Conversation

@salmon-21
Copy link

Summary

When the authorization server (e.g. Dex) runs on an internal network with its issuer set to the public gateway URL, external clients receive internal URLs they cannot reach, and the gateway encounters a circular dependency fetching JWKS from itself.

This PR fixes three related issues that arise in remote/reverse-proxy deployments where authorization.server differs from host:

  • Authorization redirect: rewrites the redirect URL to use the public host instead of the internal auth server address
  • Discovery metadata: adds rewriteMetadataURLs() to rewrite all URL fields in the /.well-known/oauth-authorization-server response from internal to public
  • JWKS circular dependency: extracts the path from the advertised jwks_uri and prepends the internal authorization.server address, so the gateway fetches keys directly from the auth server instead of from itself
  • Auth server endpoint proxy: when authorizationProxyEnabled is set, reverse-proxies auth server endpoints (token, keys, userinfo, etc.) derived from the metadata so external clients can reach them through the public gateway URL

Example scenario

host: https://public-gateway.example.com/
authorization:
  server: http://dex:5556/  # internal, not reachable from outside
  authorizationProxyEnabled: true

Without this fix, external clients receive URLs like http://dex:5556/token in the discovery metadata and cannot complete the OAuth flow.

Test plan

  • Unit tests for authServerProxyPaths() (5 cases: standard extraction, deduplication, empty metadata, invalid values, prefix patterns)
  • go build ./... passes
  • Manually tested full OAuth flow (DCR → authorization → GitHub login → callback → token exchange → authenticated MCP access) with Dex issuer set to public gateway URL

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings March 7, 2026 07:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves OAuth behavior when the authorization server is only reachable on an internal network but advertises public URLs (typical reverse-proxy / remote deployment setup). It aims to ensure external clients receive reachable gateway URLs while the gateway itself can still talk directly to the internal auth server (notably for JWKS).

Changes:

  • Rewrites the authorization redirect URL to use the configured public host.
  • Rewrites discovery metadata URL fields from internal auth-server URLs to public gateway URLs.
  • Adds reverse-proxying for auth-server endpoints (token/jwks/userinfo/etc.) derived from metadata, and avoids JWKS self-fetch circular dependencies by using the internal auth server address.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
oauth/oauth.go Builds internal JWKS fetch URL and registers reverse-proxy routes derived from auth-server metadata; adds authServerProxyPaths.
oauth/authorization_server_metadata.go Rewrites metadata URL fields from internal auth-server URLs to the public host.
oauth/authorization.go Rewrites the authorization redirect to use the public host.
oauth/oauth_test.go Adds unit tests for authServerProxyPaths().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

salmon-21 and others added 2 commits March 7, 2026 16:40
When the authorization server (e.g. Dex) runs on an internal network
with its issuer set to the public gateway URL, three issues arise:

1. The authorization redirect sends users to the internal server URL
2. Discovery metadata exposes internal URLs to external clients
3. JWKS fetching creates a circular dependency (gateway fetches from itself)

This commit fixes all three:

- Rewrite the authorization redirect to use the public host URL
- Add rewriteMetadataURLs() to rewrite all discovery metadata URLs
  from internal to public
- Build the JWKS URI from the internal server address to break the
  circular dependency
- Reverse-proxy auth server endpoints (derived from metadata) so
  external clients can reach token, keys, userinfo, etc. through
  the public gateway URL

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Handle url.Parse error in authorization redirect instead of ignoring
- Move rewriteMetadataURLs inside authorizationProxyEnabled guard so
  URLs are only rewritten when the proxy routes exist
- Restrict metadata URL rewriting to known endpoint fields (allowlist)
  to avoid rewriting issuer which would break token validation
- Use URL parsing for scheme/host comparison instead of string prefix
  matching to prevent false matches on similar hostnames
- Use url.JoinPath for JWKS URI construction and return errors for
  unparseable URIs instead of silently falling back
- Validate paths start with "/" before registering with ServeMux to
  prevent panics on relative URIs
- Add test case for relative URI rejection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@salmon-21 salmon-21 force-pushed the fix/remote-auth-server-url-rewriting branch from 11602de to da47e79 Compare March 7, 2026 07:40
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