Bug description

When a Guest user accesses via a Guest Token, the asynchronous query function fails to work properly. The root cause lies in the handling logic of the sub field when generating JWT in async_query_manager.py.

Specifically:

Guest users (GuestUser) do not have an id attribute, and get_user_id() returns None. The code sub = str(user_id) if user_id else None causes the sub field in the JWT for Guest users to be None. JWTs lacking a valid sub field cannot pass subsequent authentication, ultimately preventing Guest users from using asynchronous query functions (such as report generation, long-running queries, etc.). Reproduction steps Generate a valid Guest Token (with necessary permissions). Log in to Superset using this Guest Token. Access features requiring asynchronous processing (e.g., executing time-consuming SQL queries, generating scheduled reports). Observe that the function fails, and the backend logs may show JWT verification errors (missing or invalid sub field). Expected behavior Guest users should be able to use asynchronous query functions normally. The JWT should contain a valid sub field based on the Guest user's unique identifier (e.g., username). Actual behavior When a Guest user triggers an asynchronous query, authentication fails due to the sub field being None in the JWT, making the function unavailable. Screenshots/recordings

Image

Config Content

LOBAL_ASYNC_QUERIES_REDIS_STREAM_PREFIX = "async-events-" GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME = 'async-token' GLOBAL_ASYNC_QUERIES_JWT_SECRET = 'xxx' GLOBAL_ASYNC_QUERIES_TRANSPORT = "polling" GLOBAL_ASYNC_QUERIES_POLLING_DELAY = 500

GUEST_ROLE_NAME = "Admin" GUEST_TOKEN_JWT_SECRET = "xxx" GUEST_TOKEN_JWT_ALGO = "HS256" GUEST_TOKEN_HEADER_NAME = "X-GuestToken" GUEST_TOKEN_JWT_EXP_SECONDS = 36002430 # 30 days GUEST_TOKEN_JWT_AUDIENCE = 'superset'

Screenshots/recordings

No response

Superset version

5.0.0

Python version

3.11

Node version

18 or greater

Browser

Chrome

Additional context

No response

Checklist

  • [x] I have searched Superset docs and Slack and didn't find a solution to my problem.
  • [x] I have searched the GitHub issue tracker and didn't find a similar bug report.
  • [x] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Comment From: rusackas

@dosu any ideas here?

Comment From: dosubot[bot]

This is a confirmed bug: when a Guest user triggers an async query, the JWT 'sub' claim is set to None, which causes authentication to fail with a 401 error. The root cause is that Guest users don't have a user ID, so the code sets 'sub' to None instead of a unique string identifier.

A practical workaround is to extend the AsyncQueryManager and override the JWT generation logic so that if user_id is None, you set 'sub' to a default string like 'guest' or the guest username. For example:

class CustomAsyncQueryManager(AsyncQueryManager):
    def register_request_handlers(self, app: Flask) -> None:
        @app.after_request
        def validate_session(response: Response) -> Response:
            # ... existing code ...
            sub = str(user_id) if user_id else "guest"
            # ... rest of the method ...

This ensures the JWT always has a valid string in 'sub', which resolves the 401 for guest/embedded users with async queries. This approach is already suggested and discussed in a recent GitHub issue (details and code sample here).

As for security, using a static string like 'guest' or a guest username as 'sub' is generally safe for guest/embedded scenarios, as long as your permissions and resource scoping are enforced elsewhere. Just avoid using sensitive or guessable information in the 'sub' claim.

No recent PRs have addressed this in mainline Superset, so a local patch or subclass is currently the best option.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X