diff --git a/nextcloud_mcp_server/auth/oauth_routes.py b/nextcloud_mcp_server/auth/oauth_routes.py index 25f028f..2bfc81d 100644 --- a/nextcloud_mcp_server/auth/oauth_routes.py +++ b/nextcloud_mcp_server/auth/oauth_routes.py @@ -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)") diff --git a/nextcloud_mcp_server/server/auth_tools.py b/nextcloud_mcp_server/server/auth_tools.py index 4c7530f..f6aa99f 100644 --- a/nextcloud_mcp_server/server/auth_tools.py +++ b/nextcloud_mcp_server/server/auth_tools.py @@ -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)