This is an automated email from the ASF dual-hosted git repository.

ephraimanierobi pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit a67604716d7e933cfae65377e0dbdcbec4be05f2
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Tue Oct 21 14:47:06 2025 +0200

    Fix refresh token middleware error handling (#56892)
    
    (cherry picked from commit d7174df9b813996a6e21c49707a626e51bdb98ce)
---
 .../api_fastapi/auth/middlewares/refresh_token.py  | 38 ++++++++++++----------
 .../auth/middlewares/test_refresh_token.py         | 14 ++++++++
 2 files changed, 35 insertions(+), 17 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 81ed8448734..5705d14ba99 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
@@ -18,6 +18,7 @@
 from __future__ import annotations
 
 from fastapi import HTTPException, Request
+from fastapi.responses import JSONResponse
 from starlette.middleware.base import BaseHTTPMiddleware
 
 from airflow.api_fastapi.app import get_auth_manager
@@ -41,25 +42,28 @@ class JWTRefreshMiddleware(BaseHTTPMiddleware):
     async def dispatch(self, request: Request, call_next):
         new_user = None
         current_token = request.cookies.get(COOKIE_NAME_JWT_TOKEN)
-        if current_token:
-            new_user = await self._refresh_user(current_token)
-            if new_user:
-                request.state.user = new_user
-
-        response = await call_next(request)
+        try:
+            if current_token:
+                new_user = await self._refresh_user(current_token)
+                if new_user:
+                    request.state.user = new_user
 
-        if new_user:
-            # If we created a new user, serialize it and set it as a cookie
-            new_token = get_auth_manager().generate_jwt(new_user)
-            secure = bool(conf.get("api", "ssl_cert", fallback=""))
-            response.set_cookie(
-                COOKIE_NAME_JWT_TOKEN,
-                new_token,
-                httponly=True,
-                secure=secure,
-                samesite="lax",
-            )
+            response = await call_next(request)
 
+            if new_user:
+                # If we created a new user, serialize it and set it as a cookie
+                new_token = get_auth_manager().generate_jwt(new_user)
+                secure = bool(conf.get("api", "ssl_cert", fallback=""))
+                response.set_cookie(
+                    COOKIE_NAME_JWT_TOKEN,
+                    new_token,
+                    httponly=True,
+                    secure=secure,
+                    samesite="lax",
+                )
+        except HTTPException as exc:
+            # If any HTTPException is raised during user resolution or 
refresh, return it as response
+            return JSONResponse(status_code=exc.status_code, 
content={"detail": exc.detail})
         return response
 
     @staticmethod
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 e87b7c3fd2f..834f864e409 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
@@ -53,6 +53,20 @@ class TestJWTRefreshMiddleware:
         call_next.assert_called_once_with(mock_request)
         mock_refresh_user.assert_not_called()
 
+    @patch.object(
+        JWTRefreshMiddleware,
+        "_refresh_user",
+        side_effect=HTTPException(status_code=403, detail="Invalid JWT token"),
+    )
+    @pytest.mark.asyncio
+    async def test_dispatch_invalid_token(self, mock_refresh_user, middleware, 
mock_request):
+        mock_request.cookies = {COOKIE_NAME_JWT_TOKEN: "valid_token"}
+        call_next = AsyncMock(return_value=Response())
+
+        response = await middleware.dispatch(mock_request, call_next)
+        assert response.status_code == 403
+        assert response.body == b'{"detail":"Invalid JWT token"}'
+
     
@patch("airflow.api_fastapi.auth.middlewares.refresh_token.get_auth_manager")
     
@patch("airflow.api_fastapi.auth.middlewares.refresh_token.resolve_user_from_token")
     @pytest.mark.asyncio

Reply via email to