pierrejeambrun commented on code in PR #70783:
URL: https://github.com/apache/airflow/pull/70783#discussion_r3767523806
##########
airflow-core/tests/unit/api_fastapi/auth/middlewares/test_refresh_token.py:
##########
@@ -146,15 +146,15 @@ async def test_dispatch_with_refreshed_user(
pytest.param("http", "", False, id="http-no-local-ssl-cert"),
],
)
+
@patch("airflow.api_fastapi.auth.middlewares.refresh_token.request_cookie_is_secure")
@patch("airflow.api_fastapi.auth.middlewares.refresh_token.get_auth_manager")
@patch("airflow.api_fastapi.auth.middlewares.refresh_token.resolve_user_from_token")
- @patch("airflow.api_fastapi.auth.middlewares.refresh_token.conf")
@pytest.mark.asyncio
async def test_dispatch_cookie_secure_flag(
Review Comment:
`mock_request_cookie_is_secure` is mocking the secure flag. `"scheme",
"ssl_cert"` parametrization isn't doing anything now, can be removed.
##########
providers/fab/src/airflow/providers/fab/auth_manager/fab_auth_manager.py:
##########
@@ -373,11 +373,14 @@ def build_public_user(self, *, session: Session =
NEW_SESSION) -> AnonymousUser
def get_fastapi_middlewares(self) -> list[tuple[_MiddlewareFactory[Any],
dict[str, Any]]]:
"""Register the FAB public-access middleware when public access is
configured."""
+ middleware = super().get_fastapi_middlewares() if AIRFLOW_V_3_3_PLUS
else []
Review Comment:
Condition isn't good there, 3.3.1 was just released, this will be shipped in
3.3.2 I guess.
##########
airflow-core/src/airflow/api_fastapi/auth/middlewares/refresh_token.py:
##########
@@ -45,58 +50,114 @@ class JWTRefreshMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
new_token = None
- current_token = request.cookies.get(COOKIE_NAME_JWT_TOKEN)
+ current_user = None
+ new_user = None
try:
- if current_token is not None:
- try:
- new_user, current_user = await
self._refresh_user(current_token)
- if user := (new_user or current_user):
- # Stamp the trust sentinel alongside the user so
`get_user()`
- # can distinguish this trusted assignment from a stray
write
- # by unrelated middleware.
- request.state.user = user
- request.state.user_authenticated_via =
USER_INJECTED_BY_TRUSTED_MIDDLEWARE
- 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)
- except (HTTPException,
AuthManagerRefreshTokenExpiredException):
- # Receive a HTTPException when the Airflow token is expired
- # Receive a AuthManagerRefreshTokenExpiredException when
the potential underlying refresh
- # token used by the auth manager is expired
- new_token = ""
+ try:
+ new_user, current_user = await self._refresh_user(request)
+ except (HTTPException, AuthManagerRefreshTokenExpiredException):
+ # Receive a HTTPException when the Airflow token is expired
+ # Receive a AuthManagerRefreshTokenExpiredException when the
potential underlying refresh
+ # token used by the auth manager is expired
+ new_token = ""
+
+ if user := (new_user or current_user):
+ # Stamp the trust sentinel alongside the user so `get_user()`
+ # can distinguish this trusted assignment from a stray write
+ # by unrelated middleware.
+ request.state.user = user
+ request.state.user_authenticated_via =
USER_INJECTED_BY_TRUSTED_MIDDLEWARE
response = await call_next(request)
- if new_token is not None:
+ if new_user or new_token is not None:
+ secure = request_cookie_is_secure(request)
cookie_path = get_cookie_path()
- secure = request.base_url.scheme == "https" or
bool(conf.get("api", "ssl_cert", fallback=""))
- response.set_cookie(
- COOKIE_NAME_JWT_TOKEN,
- new_token,
- path=cookie_path,
- httponly=True,
- secure=secure,
- samesite="lax",
- max_age=0 if new_token == "" else None,
- )
- # Clear any stale _token cookie at root path "/".
- # Older Airflow instances may have set the cookie there;
- # without this, the root-path cookie keeps being sent on
- # every request, causing an infinite redirect loop.
- if cookie_path != "/":
- response.delete_cookie(
Review Comment:
delete cookie was replaced with a call to `set_cookie`. It's not exactly the
same, can we keep `delete_cookie`. (expires isn't passed down)
##########
providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py:
##########
@@ -328,8 +329,12 @@ def test_get_fastapi_middlewares_disabled(self, flask_app,
auth_manager_with_app
"""No middleware is registered when public access is not configured."""
previous = flask_app.config.get("AUTH_ROLE_PUBLIC")
flask_app.config["AUTH_ROLE_PUBLIC"] = None
+ base_middleware = []
+ if AIRFLOW_V_3_4_PLUS:
Review Comment:
Why AIRFLOW_V_3_4_PLUS here?
##########
airflow-core/src/airflow/api_fastapi/auth/managers/base_auth_manager.py:
##########
@@ -180,7 +180,17 @@ def get_fastapi_middlewares(self) ->
list[tuple[_MiddlewareFactory[Any], dict[st
unauthenticated requests when public access is configured) should
override this
method.
"""
- return []
+ return [self._get_jwt_refresh_middleware()]
+
+ def _get_jwt_refresh_middleware(self) -> tuple[_MiddlewareFactory[Any],
dict[str, Any]]:
+ """
+ Return the JWTRefreshMiddleware to refresh the Airflow JWT token.
+
+ :important: The JWTRefreshMiddleware should be included in
get_fastapi_middlewares()
+ """
+ from airflow.api_fastapi.auth.middlewares.refresh_token import
JWTRefreshMiddleware
Review Comment:
Why a local import?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]