mcp_oauth: configurable redirect_host (WAF-safe localhost redirect URIs)
Reclaim.ai's AWS API Gateway WAF 403s any /oauth2/authorize request whose query string contains a literal 127.0.0.1, so the SDK's hardcoded redirect_uri made the browser flow impossible. New optional oauth config key redirect_host (default 127.0.0.1, unchanged behavior) lets a server entry use localhost instead. Integrated into _resolve_redirect_uri so it composes with redirect_uri: an explicit redirect_uri wins; redirect_host only rewrites the loopback default's hostname.fix/verification-admin-route-recovery
parent
d0afcb125c
commit
dc419d6e80
|
|
@ -30,6 +30,7 @@ Configuration in config.yaml::
|
||||||
scope: "read write" # default: server-provided
|
scope: "read write" # default: server-provided
|
||||||
redirect_port: 0 # 0 = auto-pick free port
|
redirect_port: 0 # 0 = auto-pick free port
|
||||||
redirect_uri: "https://proxy/callback" # default: loopback callback
|
redirect_uri: "https://proxy/callback" # default: loopback callback
|
||||||
|
redirect_host: "localhost" # loopback hostname (WAF-safe)
|
||||||
client_name: "My Custom Client" # default: "Hermes Agent"
|
client_name: "My Custom Client" # default: "Hermes Agent"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -923,12 +924,23 @@ def _resolve_redirect_uri(cfg: dict, port: int) -> str:
|
||||||
|
|
||||||
A configured ``redirect_uri`` lets the callback go through a proxy (e.g. a
|
A configured ``redirect_uri`` lets the callback go through a proxy (e.g. a
|
||||||
Tailscale Funnel exposing a public HTTPS URL that forwards to localhost);
|
Tailscale Funnel exposing a public HTTPS URL that forwards to localhost);
|
||||||
otherwise we default to ``http://127.0.0.1:<port>/callback``. An empty value
|
otherwise we default to ``http://<redirect_host>:<port>/callback``. An empty
|
||||||
is treated as unset. Both the client metadata and any pre-registered client
|
value is treated as unset. Both the client metadata and any pre-registered
|
||||||
info must derive the redirect_uri here so they stay identical — a mismatch
|
client info must derive the redirect_uri here so they stay identical — a
|
||||||
makes the authorization server reject the callback.
|
mismatch makes the authorization server reject the callback.
|
||||||
|
|
||||||
|
``redirect_host`` (default ``127.0.0.1``) tweaks only the hostname of the
|
||||||
|
loopback callback. Some providers' WAFs (e.g. Reclaim.ai's AWS API Gateway)
|
||||||
|
reject any authorize request whose query string contains a literal
|
||||||
|
``127.0.0.1``, returning ``{"message":"Forbidden"}``; ``redirect_host:
|
||||||
|
localhost`` works around that. The callback listener still binds
|
||||||
|
``127.0.0.1`` either way.
|
||||||
"""
|
"""
|
||||||
return cfg.get("redirect_uri") or f"http://127.0.0.1:{port}/callback"
|
configured = cfg.get("redirect_uri")
|
||||||
|
if configured:
|
||||||
|
return configured
|
||||||
|
host = cfg.get("redirect_host") or "127.0.0.1"
|
||||||
|
return f"http://{host}:{port}/callback"
|
||||||
|
|
||||||
|
|
||||||
def _build_client_metadata(cfg: dict) -> "OAuthClientMetadata":
|
def _build_client_metadata(cfg: dict) -> "OAuthClientMetadata":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue