feat: add self-signed SSL certificate support for Nextcloud connections

Add NEXTCLOUD_VERIFY_SSL and NEXTCLOUD_CA_BUNDLE env vars to configure
TLS certificate verification for all outbound Nextcloud connections.
Centralizes SSL config via a new HTTP client factory (http.py) used by
all 27 Nextcloud-bound call sites, including API clients, OIDC endpoints,
OAuth flows, and health checks.

Closes #560

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-02-16 09:21:21 +01:00
co-authored by Claude Opus 4.6
parent df3cce4370
commit 1707b2e6e1
21 changed files with 383 additions and 38 deletions
+6 -5
View File
@@ -27,7 +27,6 @@ import time
from base64 import urlsafe_b64encode
from urllib.parse import urlencode
import httpx
import jwt
from starlette.requests import Request
from starlette.responses import JSONResponse, RedirectResponse
@@ -35,6 +34,8 @@ from starlette.responses import JSONResponse, RedirectResponse
from nextcloud_mcp_server.auth.client_registry import get_client_registry
from nextcloud_mcp_server.auth.storage import RefreshTokenStorage
from ..http import nextcloud_httpx_client
logger = logging.getLogger(__name__)
@@ -218,7 +219,7 @@ async def oauth_authorize(request: Request) -> RedirectResponse | JSONResponse:
)
# Fetch authorization endpoint from discovery
async with httpx.AsyncClient() as http_client:
async with nextcloud_httpx_client() as http_client:
response = await http_client.get(discovery_url)
response.raise_for_status()
discovery = response.json()
@@ -354,7 +355,7 @@ async def oauth_authorize_nextcloud(
status_code=500,
)
async with httpx.AsyncClient() as http_client:
async with nextcloud_httpx_client() as http_client:
response = await http_client.get(discovery_url)
response.raise_for_status()
discovery = response.json()
@@ -462,7 +463,7 @@ async def oauth_callback_nextcloud(request: Request):
callback_uri = f"{mcp_server_url}/oauth/callback"
discovery_url = oauth_config.get("discovery_url")
async with httpx.AsyncClient() as http_client:
async with nextcloud_httpx_client() as http_client:
response = await http_client.get(discovery_url)
response.raise_for_status()
discovery = response.json()
@@ -482,7 +483,7 @@ async def oauth_callback_nextcloud(request: Request):
token_params["code_verifier"] = code_verifier
# Exchange code for tokens
async with httpx.AsyncClient() as http_client:
async with nextcloud_httpx_client() as http_client:
response = await http_client.post(
token_endpoint,
data=token_params,