rsprudencio opened a new pull request, #37862:
URL: https://github.com/apache/superset/pull/37862

   ### SUMMARY
   
   When `GLOBAL_ASYNC_QUERIES` is enabled and `get_user_id()` returns `None` 
(guest users, embedded dashboards, session expiry), the `validate_session`
   after-request handler creates JWT tokens with `sub: None`. PyJWT 2.10.1's 
strict RFC 7519 validation requires `sub` to be a string when present,
   causing `InvalidSubjectError` on decode in `parse_channel_id_from_request()` 
— resulting in `AsyncQueryTokenException` and 401 failures for all
   subsequent async queries.
   
   **Fix:** Conditionally include the `sub` claim only when `user_id` is not 
`None`. RFC 7519 specifies `sub` as optional, so omitting it entirely is
   valid and PyJWT skips validation for missing claims.
   
   ```python
   # Before (buggy):
   sub = str(user_id) if user_id else None
   token = jwt.encode({"channel": async_channel_id, "sub": sub}, ...)
   
   # After (fixed):
   payload = {"channel": async_channel_id}
   if user_id:
       payload["sub"] = str(user_id)
   token = jwt.encode(payload, ...)
   
   Fixes: #34696 #34611 #31492 #33561 #34337 #32219
   
   BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   N/A — backend JWT handling change, no UI impact.
   
   TESTING INSTRUCTIONS
   
   Prerequisites: A running Superset dev environment with GLOBAL_ASYNC_QUERIES 
= True in superset_config.py.
   
   Reproduce the bug (on master, before fix):
   
   docker compose exec -T superset python3 << 'EOF'
   from superset.app import create_app
   from superset.async_events.async_query_manager import AsyncQueryManager
   from unittest.mock import patch
   from flask import request
   
   app = create_app()
   with app.app_context():
       mgr = AsyncQueryManager()
       mgr.register_request_handlers(app)
       mgr._jwt_secret = app.config["GLOBAL_ASYNC_QUERIES_JWT_SECRET"]
       mgr._jwt_cookie_name = 
app.config.get("GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME", "async_access")
       mgr._jwt_cookie_secure = False
       mgr._jwt_cookie_domain = None
       mgr._jwt_cookie_samesite = "Lax"
   
       # Step 1: Guest user request → after_request creates JWT cookie
       with patch("superset.async_events.async_query_manager.get_user_id", 
return_value=None):
           resp = app.test_client().get("/health")
           token = [v for k, v in resp.headers if k == "Set-Cookie" and 
mgr._jwt_cookie_name in v][0]
           token = token.split("=", 1)[1].split(";")[0]
   
       # Step 2: Next request with that cookie → real code decodes it
       with app.test_request_context(headers={"Cookie": 
f"{mgr._jwt_cookie_name}={token}"}):
           try:
               channel = mgr.parse_channel_id_from_request(request)
               print(f"✅ Fix works! Channel: {channel}")
           except Exception as e:
               print(f"🐛 Bug! {e}")
   EOF
   ```
   
   Expected on master: 🐛 Bug! Failed to parse token (caused by 
InvalidSubjectError: Subject must be a string at line 204)
   
   Expected with this fix: ✅ Fix works! Channel: <uuid>
   
   The test exercises the real code path end-to-end: validate_session 
(after_request handler) creates the JWT, then parse_channel_id_from_request
   decodes it — no manual jwt.encode/decode in the test.
   
   ADDITIONAL INFORMATION
       - Has associated issue: #34696, #34611, #31492, #33561, #34337, #32219
       - Required feature flags: None (GLOBAL_ASYNC_QUERIES config option 
required to test)
       - Changes UI: No
       - Includes DB Migration: No
       - Introduces new feature or API: No
       - Removes existing feature or API: No
   
   CHECKLIST
   
       - PR title follows Conventional Commits format
       - Backward compatible — no behavior change for authenticated users
       - Minimal change: 7 lines changed in one file
       - Tests added/updated
       - Documentation updated


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