From 2fe36fce75267bd31cb1ff824f4606413be69072 Mon Sep 17 00:00:00 2001 From: vincbeck Date: Mon, 20 Oct 2025 15:15:29 -0400 Subject: [PATCH] Handle invalid token in `JWTRefreshMiddleware` --- .../api_fastapi/auth/middlewares/refresh_token.py | 7 +++++-- .../auth/middlewares/test_refresh_token.py | 14 +++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py b/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py index f304eb9517f65..81ed844873458 100644 --- a/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py +++ b/airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py @@ -17,7 +17,7 @@ # under the License. from __future__ import annotations -from fastapi import Request +from fastapi import HTTPException, Request from starlette.middleware.base import BaseHTTPMiddleware from airflow.api_fastapi.app import get_auth_manager @@ -64,5 +64,8 @@ async def dispatch(self, request: Request, call_next): @staticmethod async def _refresh_user(current_token: str) -> BaseUser | None: - user = await resolve_user_from_token(current_token) + try: + user = await resolve_user_from_token(current_token) + except HTTPException: + return None return get_auth_manager().refresh_user(user=user) diff --git a/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py b/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py index 87648a2be2b6c..e87b7c3fd2f15 100644 --- a/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py +++ b/airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py @@ -20,7 +20,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -from fastapi import Request, Response +from fastapi import HTTPException, Request, Response from airflow.api_fastapi.auth.managers.base_auth_manager import COOKIE_NAME_JWT_TOKEN from airflow.api_fastapi.auth.managers.models.base_user import BaseUser @@ -72,6 +72,18 @@ async def test_dispatch_no_refreshed_token( mock_resolve_user_from_token.assert_called_once_with("valid_token") mock_auth_manager.generate_jwt.assert_not_called() + @patch("airflow.api_fastapi.auth.middlewares.refresh_token.resolve_user_from_token") + @pytest.mark.asyncio + async def test_dispatch_expired_token(self, mock_resolve_user_from_token, middleware, mock_request): + mock_request.cookies = {COOKIE_NAME_JWT_TOKEN: "invalid_token"} + mock_resolve_user_from_token.side_effect = HTTPException(status_code=403) + + call_next = AsyncMock(return_value=Response()) + await middleware.dispatch(mock_request, call_next) + + call_next.assert_called_once_with(mock_request) + mock_resolve_user_from_token.assert_called_once_with("invalid_token") + @pytest.mark.asyncio @patch("airflow.api_fastapi.auth.middlewares.refresh_token.get_auth_manager") @patch("airflow.api_fastapi.auth.middlewares.refresh_token.resolve_user_from_token")