fix: address review feedback — security, caching, CI 429 retry
- Add 429 retry with exponential backoff to register_client() (fixes CI oauth matrix failures from parallel DCR requests) - Make client_id, redirect_uri, and PKCE mandatory at token endpoint - Add null-checks for discovery_url and OAuth credentials in proxy flows - Add OIDC discovery document caching with 5-min TTL - Add per-IP rate limiting on /oauth/register DCR proxy - Discover DCR endpoint from OIDC discovery instead of hardcoding - Extract extract_user_id_from_token to auth/token_utils.py (breaks circular imports between server/ and auth/ layers) - Add TTL scope cache in scope_authorization.py (avoids DB hit per tool) - Add defense-in-depth scope validation in storage layer - Broaden elicitation exception handling with graceful fallback - Add idempotentHint to nc_auth_check_status, return "pending" status after accepted elicitation, add polling interval to description - Change ALL_SUPPORTED_SCOPES from tuple to frozenset for O(1) lookups - Replace Optional[str] with str | None throughout config.py - Use default_factory for ProxyCodeEntry/ASProxySession dataclasses - Add proxy code/session cleanup to background loop - Fix OIDC verification CI step to only run for oauth/login-flow modes - Add unit tests for access.py REST endpoints (10 tests) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
0a53aa5fcd
commit
f43343356e
@@ -1532,13 +1532,19 @@ def get_app(transport: str = "streamable-http", enabled_apps: list[str] | None =
|
||||
mcp_app = mcp.streamable_http_app()
|
||||
|
||||
async def _login_flow_cleanup_loop() -> None:
|
||||
"""Periodically clean up expired Login Flow v2 sessions."""
|
||||
"""Periodically clean up expired Login Flow v2 sessions and proxy codes."""
|
||||
from nextcloud_mcp_server.auth.oauth_routes import ( # noqa: PLC0415
|
||||
_cleanup_expired_proxy_codes,
|
||||
)
|
||||
|
||||
while True:
|
||||
try:
|
||||
storage = await get_shared_storage()
|
||||
count = await storage.delete_expired_login_flow_sessions()
|
||||
if count:
|
||||
logger.info(f"Cleaned up {count} expired login flow sessions")
|
||||
# Also clean up expired AS proxy codes/sessions
|
||||
_cleanup_expired_proxy_codes()
|
||||
except Exception as e:
|
||||
logger.warning(f"Login flow cleanup error: {e}")
|
||||
await anyio.sleep(3600) # Every hour
|
||||
|
||||
Reference in New Issue
Block a user