diff --git a/gns3server/api/routes/mcp/__init__.py b/gns3server/api/routes/mcp/__init__.py index 021f66b99..47438b9c8 100644 --- a/gns3server/api/routes/mcp/__init__.py +++ b/gns3server/api/routes/mcp/__init__.py @@ -213,14 +213,16 @@ async def _resolve_token(token: str) -> str | None: Returns None if the token is invalid. """ - # Try JWT first - try: - token_data = auth_service.get_token_data(token) - _jwt_username_var.set(token_data.username) - _jwt_token_version_var.set(token_data.token_version) - return token - except Exception: - pass + # API keys (gns3_...) are never valid JWTs — skip the JWT attempt for them + # so it doesn't log a spurious "JWT rejected" line on every API-key connection. + if not token.startswith("gns3_"): + try: + token_data = auth_service.get_token_data(token) + _jwt_username_var.set(token_data.username) + _jwt_token_version_var.set(token_data.token_version) + return token + except Exception: + pass # Try API key — format: gns3__ → O(1) lookup if token.startswith("gns3_") and _app is not None: diff --git a/gns3server/services/authentication.py b/gns3server/services/authentication.py index 6103ee6f9..90f943b99 100644 --- a/gns3server/services/authentication.py +++ b/gns3server/services/authentication.py @@ -115,10 +115,10 @@ class AuthService: token_use: str = payload.claims.get("type", "access") token_data = TokenData(username=username, token_version=token_version, token_use=token_use) except BadSignatureError as e: - log.error("JWT rejected: bad signature (header alg: '%s', error: %s)", _extract_alg(token), e) + log.warning("JWT rejected: bad signature (header alg: '%s', error: %s)", _extract_alg(token), e) raise auth_error("Invalid token signature") except (JoseError, ValidationError, ValueError) as e: - log.error("JWT rejected: %s: %s (header alg: '%s')", type(e).__name__, e, _extract_alg(token)) + log.warning("JWT rejected: %s: %s (header alg: '%s')", type(e).__name__, e, _extract_alg(token)) raise auth_error(f"Invalid token ({type(e).__name__})") return token_data