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


##########
airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_router.py:
##########
@@ -61,9 +120,49 @@ def test_expiring_token_is_reissued(
     lifespan.registry.register_value(JWTValidator, auth)
     # In order to test this we need any endpoint to hit. The easiest one to 
use is variable get
 
-    response = client.get("/execution/variables/key1", 
headers={"Authorization": "Bearer dummy"})
+    response = jwt_bearer_client.get("/execution/variables/key1", 
headers={"Authorization": "Bearer dummy"})
 
     if expect_refreshed_token:
         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(
+    jwt_bearer_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 starts, and the middleware runs. In the old code the 
middleware would call
+    avalidated_claims a second time and get ExpiredSignatureError — no 
Refreshed-API-Token
+    header would be set, and the task would die on the next heartbeat.
+
+    With the fix the middleware reads claims from request.scope (set by 
JWTBearer) instead of
+    calling avalidated_claims again, so it still issues a fresh token even 
when the original
+    has since expired.
+    """
+    moment = 1743451846
+    auth = AsyncMock(spec=JWTValidator)
+    auth.avalidated_claims.return_value = {
+        "sub": "edb09971-4e0e-4221-ad3f-800852d38085",
+        "iat": moment,
+        "exp": moment + 600,
+    }
+
+    # Move time to 1 second past the token's expiry. JWTBearer already 
accepted the token
+    # (mocked); the middleware must still issue a refresh using the cached 
claims rather than
+    # silently dropping it.
+    time_machine.move_to(moment + 601, tick=False)
+
+    lifespan.registry.register_value(JWTValidator, auth)
+
+    response = jwt_bearer_client.get("/execution/variables/key1", 
headers={"Authorization": "Bearer dummy"})
+
+    assert "Refreshed-API-Token" in response.headers

Review Comment:
   This isn't really testing the TOCTOU bug - fairly sure this would pass 
without any code changes. 
   
   I think what you need to do is register a custom route that does a time 
travel inside it



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