Skip to content

Commit 826d322

Browse files
rgambeeRafaelPoclaude
authored
Allow Supabase JWT passthrough (#238)
* Allow Supabase JWT passthrough * Add EXTRA_ALLOWED_HOSTS env var for DNS rebinding protection Allows configuring additional allowed Host headers via a comma-separated env var, enabling cross-Docker-network access (e.g. host.docker.internal). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Rafael Poyiadzi <rafael@futuresearch.ai> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 42dd939 commit 826d322

3 files changed

Lines changed: 23 additions & 4 deletions

File tree

everyrow-mcp/deploy/docker-compose.local.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Local development overrides.
1+
# Local development overrides — NOT for production use.
22
# Usage: docker compose -f docker-compose.yaml -f docker-compose.local.yaml up
33
services:
44
redis:
@@ -9,3 +9,4 @@ services:
99
environment:
1010
MCP_SERVER_URL: "${MCP_SERVER_URL:-http://localhost:8000}"
1111
TRUST_PROXY_HEADERS: "${TRUST_PROXY_HEADERS:-false}"
12+
EXTRA_ALLOWED_HOSTS: "host.docker.internal:*" # local dev only — widens DNS rebinding allowlist

everyrow-mcp/src/everyrow_mcp/auth.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,21 @@ async def exchange_authorization_code(
496496
supabase_refresh_token=authorization_code.supabase_refresh_token,
497497
)
498498

499-
async def load_access_token(self, token: str) -> AccessToken | None: # noqa: ARG002
500-
return None
499+
async def load_access_token(self, token: str) -> AccessToken | None:
500+
# Accept raw Supabase JWTs directly (JWT passthrough path).
501+
# This allows the CC app to forward the user's session JWT without an
502+
# OAuth dance. Backward-compatible: clients using the existing OAuth
503+
# flow continue to receive MCP-issued tokens, which are Supabase JWTs
504+
# under the hood, so they are also accepted here.
505+
result = await self._token_verifier.verify_token(token)
506+
if result is None:
507+
return None
508+
return AccessToken(
509+
token=result.token,
510+
client_id=result.client_id,
511+
scopes=["everyrow"],
512+
expires_at=result.expires_at,
513+
)
501514

502515
async def load_refresh_token(
503516
self, client: OAuthClientInformationFull, refresh_token: str

everyrow-mcp/src/everyrow_mcp/http_config.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import contextvars
66
import logging
7+
import os
78
import time as _time
89
from urllib.parse import urlparse
910

@@ -174,9 +175,13 @@ def _configure_mcp_auth(
174175
client_registration_options=ClientRegistrationOptions(enabled=True),
175176
)
176177
hostname = urlparse(settings.mcp_server_url).hostname or "localhost"
178+
allowed_hosts = [hostname]
179+
extra = os.environ.get("EXTRA_ALLOWED_HOSTS", "")
180+
if extra:
181+
allowed_hosts.extend(h.strip() for h in extra.split(",") if h.strip())
177182
mcp.settings.transport_security = TransportSecuritySettings(
178183
enable_dns_rebinding_protection=True,
179-
allowed_hosts=[hostname],
184+
allowed_hosts=allowed_hosts,
180185
)
181186

182187

0 commit comments

Comments
 (0)