From 057e25b6538b634d53010457e42f6cc5eca46af7 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Mon, 13 Oct 2025 23:34:49 +0200 Subject: [PATCH] chore: Add support for overriding public issuer URL test: Add patch for PKCE support --- ...-challenge-methods-to-discovery-documen.patch | 16 ++++++++++++++++ app-hooks/post-installation/install-oidc-app.sh | 2 ++ docker-compose.yml | 6 +++++- nextcloud_mcp_server/app.py | 9 +++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 app-hooks/post-installation/0002-Add-PKCE-code-challenge-methods-to-discovery-documen.patch diff --git a/app-hooks/post-installation/0002-Add-PKCE-code-challenge-methods-to-discovery-documen.patch b/app-hooks/post-installation/0002-Add-PKCE-code-challenge-methods-to-discovery-documen.patch new file mode 100644 index 0000000..99f70f4 --- /dev/null +++ b/app-hooks/post-installation/0002-Add-PKCE-code-challenge-methods-to-discovery-documen.patch @@ -0,0 +1,16 @@ +diff --git a/lib/Util/DiscoveryGenerator.php b/lib/Util/DiscoveryGenerator.php +index ee3cd57..6429f94 100644 +--- a/lib/Util/DiscoveryGenerator.php ++++ b/lib/Util/DiscoveryGenerator.php +@@ -171,6 +171,11 @@ class DiscoveryGenerator + $discoveryPayload['registration_endpoint'] = $host . $this->urlGenerator->linkToRoute('oidc.DynamicRegistration.registerClient', []); + } + ++ // Add PKCE support if enabled ++ if ($this->appConfig->getAppValueBool('proof_key_for_code_exchange', false)) { ++ $discoveryPayload['code_challenge_methods_supported'] = ['S256']; ++ } ++ + $this->logger->info('Request to Discovery Endpoint.'); + + $response = new JSONResponse($discoveryPayload); diff --git a/app-hooks/post-installation/install-oidc-app.sh b/app-hooks/post-installation/install-oidc-app.sh index 8858f52..50c59ab 100755 --- a/app-hooks/post-installation/install-oidc-app.sh +++ b/app-hooks/post-installation/install-oidc-app.sh @@ -11,9 +11,11 @@ php /var/www/html/occ app:enable oidc php /var/www/html/occ app:enable user_oidc patch -u /var/www/html/custom_apps/user_oidc/lib/User/Backend.php -i /docker-entrypoint-hooks.d/post-installation/0001-Fix-Bearer-token-authentication-causing-session-logo.patch +patch -u /var/www/html/custom_apps/oidc/lib/Util/DiscoveryGenerator.php -i /docker-entrypoint-hooks.d/post-installation/0002-Add-PKCE-code-challenge-methods-to-discovery-documen.patch # Configure OIDC Identity Provider with dynamic client registration enabled php /var/www/html/occ config:app:set oidc dynamic_client_registration --value='true' +php /var/www/html/occ config:app:set oidc proof_key_for_code_exchange --value=true --type=boolean # Configure user_oidc to validate bearer tokens from the OIDC Identity Provider php /var/www/html/occ config:system:set user_oidc oidc_provider_bearer_validation --value=true --type=boolean diff --git a/docker-compose.yml b/docker-compose.yml index 69bd71d..1421b57 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: #- command: chown -R www-data:www-data /var/www/html && while ! nc -z db 3306; do sleep 1; echo sleeping; done #user: root ports: - - 127.0.0.1:8080:80 + - 0.0.0.0:8080:80 depends_on: - redis - db @@ -67,8 +67,12 @@ services: - app ports: - 127.0.0.1:8001:8001 + #extra_hosts: + #- "host.docker.internal:host-gateway" environment: - NEXTCLOUD_HOST=http://app:80 + - NEXTCLOUD_MCP_SERVER_URL=http://127.0.01:8001 + - NEXTCLOUD_PUBLIC_ISSUER_URL=http://127.0.0.1:8080 # No USERNAME/PASSWORD - will use OAuth volumes: - oauth-client-storage:/app/.oauth diff --git a/nextcloud_mcp_server/app.py b/nextcloud_mcp_server/app.py index 91afaa6..c99c57e 100644 --- a/nextcloud_mcp_server/app.py +++ b/nextcloud_mcp_server/app.py @@ -214,6 +214,15 @@ async def setup_oauth_config(): userinfo_uri = discovery["userinfo_endpoint"] registration_endpoint = discovery.get("registration_endpoint") + # Allow override of public issuer URL for clients + # (useful when MCP server accesses Nextcloud via internal URL + # but needs to advertise a different URL to clients) + public_issuer = os.getenv("NEXTCLOUD_PUBLIC_ISSUER_URL") + if public_issuer: + public_issuer = public_issuer.rstrip("/") + logger.info(f"Using public issuer URL for clients: {public_issuer}") + issuer = public_issuer + # Handle client registration client_id = os.getenv("NEXTCLOUD_OIDC_CLIENT_ID") client_secret = os.getenv("NEXTCLOUD_OIDC_CLIENT_SECRET")