ashb commented on code in PR #68054:
URL: https://github.com/apache/airflow/pull/68054#discussion_r3380660675


##########
airflow-core/src/airflow/api_fastapi/execution_api/app.py:
##########
@@ -135,25 +136,22 @@ async def dispatch(self, request: Request, call_next):
         response: Response = await call_next(request)
 
         refreshed_token: str | None = None
-        auth_header = request.headers.get("authorization")
-        if auth_header and auth_header.lower().startswith("bearer "):
-            token = auth_header.split(" ", 1)[1]
+        token = request.scope.get(_REQUEST_SCOPE_TOKEN_KEY)
+        if token:
             try:
-                async with svcs.Container(request.app.state.svcs_registry) as 
services:
-                    validator: JWTValidator = await services.aget(JWTValidator)
-                    claims = await validator.avalidated_claims(token, {})
-
-                    # Workload tokens are long-lived and meant to survive queue
-                    # wait times so avoid refreshing them. If avalidated_claims
-                    # raises for a workload token, the outer except handles it.
-                    if claims.get("scope") == "workload":
-                        return response
-
-                    now = int(time.time())
-                    token_lifetime = int(claims.get("exp", 0)) - 
int(claims.get("iat", 0))
-                    refresh_when_less_than = max(int(token_lifetime * 0.20), 
30)
-                    valid_left = int(claims.get("exp", 0)) - now
-                    if valid_left <= refresh_when_less_than:
+                claims = {"sub": str(token.id), **token.claims.model_dump()}

Review Comment:
   What uses the `sub` claim? It looks unused.



##########
airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_router.py:
##########
@@ -67,3 +126,41 @@ def test_expiring_token_is_reissued(
         assert "Refreshed-API-Token" in response.headers
     else:
         assert "Refreshed-API-Token" not in response.headers
+    # avalidated_claims must be called exactly once — by JWTBearer only, not 
by the middleware.
+    auth.avalidated_claims.assert_awaited_once_with("dummy", {})
+
+
[email protected]_test
+def test_token_expiring_mid_request_is_reissued_without_revalidation(client, 
exec_app: FastAPI, time_machine):
+    """Middleware reissues from cached JWTBearer claims without re-validating 
the token.
+
+    Regression test for the TOCTOU race in JWTReissueMiddleware: a heartbeat 
arrives with a
+    token that has ~0s left, JWTBearer validates it (still technically valid 
at that moment),
+    the request completes, and the middleware runs. In the old code the 
middleware would call

Review Comment:
   ```suggestion
       the request starts, and the middleware runs. In the old code the 
middleware would call
   ```
   
   I think?



##########
airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_router.py:
##########
@@ -20,17 +20,76 @@
 from unittest.mock import AsyncMock
 
 import pytest
-from fastapi import FastAPI
+import svcs
+from fastapi import FastAPI, HTTPException, Request, status
+from fastapi.security import HTTPBearer
+from fastapi.testclient import TestClient
 
 from airflow.api_fastapi.auth.tokens import JWTValidator
 from airflow.api_fastapi.execution_api.app import lifespan
+from airflow.api_fastapi.execution_api.datamodels.token import TIClaims, 
TIToken
+from airflow.api_fastapi.execution_api.security import (
+    _REQUEST_SCOPE_TOKEN_KEY,
+    _jwt_bearer,
+)
+
+
[email protected]
+def client():

Review Comment:
   This has a very generic fixture name, `client`, but it does stuff very 
specific to testing jwt bearer. It likely shouldn't be a module fixture, or 
should have a less generic name.  



-- 
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]

Reply via email to