fix: address PR review feedback for client registry and DCR proxy

- Document wildcard scope policy in ClientRegistry class docstring
- Add hostname None guard and IPv6 loopback (::1) to redirect URI validation
- Simplify redirect URI scheme validation into single guard clause
- Add try/finally cleanup to DCR client deletion test
- Validate 302 Location header in unknown client rejection test
- Add unit tests for IPv6 loopback, malformed URIs, and DCR proxy paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-04-05 19:29:23 +02:00
co-authored by Claude Opus 4.6
parent 7d775d2a52
commit b07b713146
4 changed files with 144 additions and 14 deletions
+21 -7
View File
@@ -36,6 +36,12 @@ class ClientRegistry:
2. Integrate with IdP client registry
3. Store client metadata in database
4. Support client updates and revocation
Scope Policy:
All clients are registered with allowed_scopes=["*"] (wildcard).
The MCP server acts as an OAuth AS proxy — it validates client
identity and redirect URIs locally, but delegates scope enforcement
to the upstream IdP (Nextcloud or Keycloak).
"""
def __init__(self, allow_dynamic_registration: bool = False):
@@ -80,13 +86,19 @@ class ClientRegistry:
continue
parsed = urlparse(redirect)
is_loopback = parsed.hostname in ("localhost", "127.0.0.1")
hostname = parsed.hostname
if hostname is None:
logger.warning(
f"Skipping client {cid!r}: cannot parse hostname "
f"from {redirect!r}"
)
continue
is_loopback = hostname in ("localhost", "127.0.0.1", "::1")
if parsed.scheme == "https":
pass # HTTPS always allowed
elif parsed.scheme == "http" and is_loopback:
pass # HTTP localhost allowed
else:
if not (
parsed.scheme == "https"
or (parsed.scheme == "http" and is_loopback)
):
logger.warning(
f"Rejecting client {cid!r}: HTTP redirect URIs are only "
f"allowed for localhost, got {redirect!r}"
@@ -205,6 +217,8 @@ class ClientRegistry:
"""
# Parse the redirect URI
parsed = urlparse(redirect_uri)
if not parsed.hostname:
return False
# Check against registered patterns
for pattern in client.redirect_uris:
@@ -213,7 +227,7 @@ class ClientRegistry:
pattern_base = pattern.replace(":*", "")
if redirect_uri.startswith(pattern_base + ":"):
# Validate it's localhost with a port
if parsed.hostname in ["localhost", "127.0.0.1"]:
if parsed.hostname in ("localhost", "127.0.0.1", "::1"):
return True
elif redirect_uri == pattern:
return True