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

rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 99841fb504b fix(async): include datasets and rev claims in guest 
channel HMAC (#41487)
99841fb504b is described below

commit 99841fb504bbc3c42c4b3055fbc783b74e368676
Author: Evan Rusackas <[email protected]>
AuthorDate: Fri Jul 24 13:29:58 2026 -0700

    fix(async): include datasets and rev claims in guest channel HMAC (#41487)
    
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 superset/async_events/async_query_manager.py       |  5 +++
 .../async_events/async_query_manager_tests.py      | 38 ++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/superset/async_events/async_query_manager.py 
b/superset/async_events/async_query_manager.py
index 7cfbd6892df..cda66bfde4a 100644
--- a/superset/async_events/async_query_manager.py
+++ b/superset/async_events/async_query_manager.py
@@ -249,6 +249,11 @@ class AsyncQueryManager:
                 "iat": token.get("iat"),
                 "exp": token.get("exp"),
                 "aud": token.get("aud"),
+                # ``datasets`` and ``rev`` are optional scope claims, so tokens
+                # that differ only in their dataset allowlist or revocation
+                # version still derive distinct channels.
+                "datasets": token.get("datasets"),
+                "rev": token.get("rev"),
             },
             sort_keys=True,
         ).encode("utf-8")
diff --git a/tests/unit_tests/async_events/async_query_manager_tests.py 
b/tests/unit_tests/async_events/async_query_manager_tests.py
index 421f4159fbb..f5b5c97c8a2 100644
--- a/tests/unit_tests/async_events/async_query_manager_tests.py
+++ b/tests/unit_tests/async_events/async_query_manager_tests.py
@@ -223,6 +223,44 @@ def 
test_parse_channel_id_from_request_as_guest_user_differs_per_token(
     assert first != second
 
 
[email protected]("superset.is_feature_enabled")
+def test_parse_channel_id_from_request_as_guest_user_differs_per_scope(
+    is_feature_enabled_mock, async_query_manager
+):
+    """
+    Tokens that differ only in the optional ``datasets`` allowlist or ``rev``
+    revocation version must still derive distinct channel ids, otherwise two
+    differently scoped embedded sessions would collide on the same stream.
+    """
+    is_feature_enabled_mock.return_value = True
+
+    base_token = {
+        "user": {},
+        "resources": [{"type": "dashboard", "id": "some-uuid"}],
+        "rls_rules": [{"clause": '"STATEID" = 3'}],
+        "iat": 1700000000.0,
+        "exp": 1700000300.0,
+        "aud": "http://0.0.0.0:8080/";,
+        "type": "guest",
+    }
+
+    request = Mock()
+    request.cookies = {}
+
+    g.user = security_manager.get_guest_user_from_token(dict(base_token))
+    baseline = async_query_manager.parse_channel_id_from_request(request)
+
+    g.user = security_manager.get_guest_user_from_token({**base_token, 
"datasets": [1]})
+    with_datasets = async_query_manager.parse_channel_id_from_request(request)
+
+    g.user = security_manager.get_guest_user_from_token({**base_token, "rev": 
1})
+    with_rev = async_query_manager.parse_channel_id_from_request(request)
+
+    assert baseline != with_datasets
+    assert baseline != with_rev
+    assert with_datasets != with_rev
+
+
 @mark.parametrize(
     "cache_type, cache_backend",
     [

Reply via email to