Class: MCP::Client::HTTP::OAuthURLGuard

Inherits:
Object
  • Object
show all
Defined in:
lib/mcp/client/http.rb

Overview

Faraday request middleware that compares the outgoing request URL against the URL snapshotted at ‘MCP::Client::HTTP#initialize` time. Registered after the user’s customizer so it sees ‘env.url` after any custom middleware has had a chance to rewrite it - closing the `Faraday env.url = URI(“attacker…”)` bypass that a plain `client.url_prefix` check would miss. The comparison includes the query string, so a middleware that rewrites `env.url.query` to a different tenant (e.g. `?tenant=evil`) is rejected as well; otherwise the audience-binding check on the OAuth side could be bypassed at the send step.

Instance Method Summary collapse

Constructor Details

#initialize(app, expected_url:) ⇒ OAuthURLGuard

Returns a new instance of OAuthURLGuard.



36
37
38
39
# File 'lib/mcp/client/http.rb', line 36

def initialize(app, expected_url:)
  @app = app
  @expected_url = expected_url
end

Instance Method Details

#call(env) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/mcp/client/http.rb', line 41

def call(env)
  effective = MCP::Client::OAuth::Discovery.canonicalize_url(env.url.to_s)
  unless effective == @expected_url
    # Surface the *canonicalized* form (no userinfo, no fragment) so
    # credentials like `user:pass@` cannot leak into logs, stack
    # traces, or exception reporters.
    raise InsecureURLError,
      "Effective request URL #{effective.inspect} does not match the URL " \
        "validated at initialize time (#{@expected_url.inspect}); refusing to send a bearer token."
  end
  @app.call(env)
end