rusackas commented on code in PR #40651:
URL: https://github.com/apache/superset/pull/40651#discussion_r3349623041


##########
tests/unit_tests/async_events/async_query_manager_tests.py:
##########
@@ -78,6 +79,68 @@ def 
test_parse_channel_id_from_request_bad_jwt(async_query_manager):
         async_query_manager.parse_channel_id_from_request(request)
 
 
+def test_generate_jwt_sets_expiration(async_query_manager):
+    """Generated tokens carry iat/exp and round-trip through parsing."""
+    import jwt
+
+    token = async_query_manager.generate_jwt({"channel": "abc", "sub": "1"})
+    claims = jwt.decode(token, JWT_TOKEN_SECRET, algorithms=["HS256"])
+
+    assert claims["channel"] == "abc"
+    assert "exp" in claims
+    assert "iat" in claims
+    assert claims["exp"] > claims["iat"]
+    assert (
+        async_query_manager.parse_channel_id_from_request(
+            Mock(cookies={"superset_async_jwt": token})
+        )
+        == "abc"
+    )
+
+
+def test_parse_channel_id_rejects_expired_token(async_query_manager):
+    """An expired token is rejected (PyJWT validates exp on decode)."""
+    past = datetime.now(tz=timezone.utc) - timedelta(hours=2)
+    expired = encode(
+        {
+            "channel": "abc",
+            "iat": past,
+            "exp": past + timedelta(hours=1),
+        },
+        JWT_TOKEN_SECRET,
+        algorithm="HS256",
+    )
+
+    with raises(AsyncQueryTokenException):
+        async_query_manager.parse_channel_id_from_request(
+            Mock(cookies={"superset_async_jwt": expired})
+        )
+
+
+def test_jwt_needs_refresh(async_query_manager):
+    """Refresh missing/legacy/expired/near-expiry tokens; keep fresh ones."""
+    now = datetime.now(tz=timezone.utc)
+
+    # Missing token
+    assert async_query_manager._jwt_needs_refresh(None) is True
+
+    # Legacy token without exp
+    legacy = encode({"channel": "abc"}, JWT_TOKEN_SECRET, algorithm="HS256")
+    assert async_query_manager._jwt_needs_refresh(legacy) is True
+
+    # Fresh token (full lifetime remaining) is not refreshed
+    fresh = async_query_manager.generate_jwt({"channel": "abc"})
+    assert async_query_manager._jwt_needs_refresh(fresh) is False
+
+    # Token in the second half of its lifetime is refreshed
+    near_expiry = encode(
+        {"channel": "abc", "iat": now, "exp": now + timedelta(minutes=10)},
+        JWT_TOKEN_SECRET,
+        algorithm="HS256",
+    )
+    assert async_query_manager._jwt_needs_refresh(near_expiry) is True

Review Comment:
   Good catch. I added an explicit assertion that an already-expired token (exp 
in the past, decode raises ExpiredSignatureError) causes `_jwt_needs_refresh` 
to return True, so a regression like catching the wrong exception type would be 
detected. The test now covers missing/legacy/fresh/near-expiry/expired.



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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to