fix: replace assert with proper guard and invalidate scope cache after provisioning

Replace `assert entry.code_challenge` with a proper if-guard returning a
500 JSON error in the token endpoint, since Python's -O flag strips
asserts and would silently disable PKCE enforcement.

Invalidate the scope cache immediately after Login Flow v2 provisioning
completes, so users no longer hit ProvisioningRequiredError for up to
5 minutes after successfully authenticating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-03-03 09:31:36 +01:00
parent 1fae6920be
commit 47fb562326
2 changed files with 14 additions and 4 deletions
+9 -3
View File
@@ -1051,9 +1051,15 @@ async def _token_authorization_code(request: Request, form) -> JSONResponse:
)
# Verify PKCE (always required — oauth_authorize mandates code_challenge)
assert entry.code_challenge, (
"code_challenge must be set (enforced by oauth_authorize)"
) # noqa: S101
if not entry.code_challenge:
logger.error("AS proxy token: code_challenge missing from stored entry")
return JSONResponse(
{
"error": "server_error",
"error_description": "Internal state error: missing PKCE challenge",
},
status_code=500,
)
if not code_verifier:
logger.warning("AS proxy token: Missing 'code_verifier' (PKCE required)")
+5 -1
View File
@@ -14,7 +14,10 @@ from mcp.types import ToolAnnotations
from nextcloud_mcp_server.auth.elicitation import present_login_url
from nextcloud_mcp_server.auth.login_flow import LoginFlowV2Client
from nextcloud_mcp_server.auth.scope_authorization import require_scopes
from nextcloud_mcp_server.auth.scope_authorization import (
invalidate_scope_cache,
require_scopes,
)
from nextcloud_mcp_server.auth.storage import get_shared_storage
from nextcloud_mcp_server.auth.token_utils import extract_user_id_from_token
from nextcloud_mcp_server.config import get_nextcloud_ssl_verify, get_settings
@@ -282,6 +285,7 @@ def register_auth_tools(mcp: FastMCP) -> None:
scopes=session.get("requested_scopes"),
username=poll_result.login_name,
)
invalidate_scope_cache(user_id)
# Clean up the flow session
await storage.delete_login_flow_session(user_id)