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

   > **Draft / `hold:testing`** — touches session/cookie lifetime behavior for 
Global Async Queries. Needs end-to-end validation before merge (see "Why 
draft").
   
   ### SUMMARY
   
   The async-queries JWT (set as the `async-token` cookie, used to authenticate 
the async event channel and the WebSocket connection) was minted **without an 
`exp` claim**, so a leaked cookie granted access to the user's async event 
channel indefinitely (CWE-613).
   
   This adds `iat`/`exp` to the token with a configurable lifetime 
(`GLOBAL_ASYNC_QUERIES_JWT_EXP_SECONDS`, default 1h) and a **sliding refresh** 
so active sessions are never disrupted:
   
   - `validate_session` (the `after_request` handler) now reissues the cookie 
whenever the token is **missing, legacy (no `exp`), expired, or past the first 
half of its lifetime**, while **reusing the existing channel** (only minting a 
brand-new channel when there isn't one for the user, as before).
   - The cookie gets a matching `max_age`.
   - PyJWT validates `exp` on decode, so an expired (e.g. leaked) token is 
rejected by `parse_channel_id_from_request` and by the WebSocket server's 
verifier.
   
   Legacy tokens without `exp` are transparently upgraded on the next request, 
so there's no flag-day.
   
   ### WHY DRAFT (`hold:testing`)
   
   This changes cookie/session lifetime semantics for GAQ. The proactive 
refresh (second-half-of-lifetime) keeps active sessions valid, but there's one 
edge worth validating: a session left **idle beyond the full token lifetime** 
will have both the cookie (`max_age`) and token expired; the first request 
afterward re-issues the cookie via `after_request`, but if that very first 
request is itself an async-query submit, it could see a transient token error 
and need a retry. Needs validation that:
   - normal active navigation never surfaces a token error (expected: proactive 
refresh covers it);
   - the WebSocket transport reconnects cleanly when the token is refreshed;
   - the long-idle edge degrades gracefully.
   
   ### TESTING INSTRUCTIONS
   
   ```
   pytest tests/unit_tests/async_events/async_query_manager_tests.py
   ```
   
   New unit tests: `generate_jwt` sets `iat`/`exp` and round-trips; an expired 
token is rejected; `_jwt_needs_refresh` refreshes 
missing/legacy/expired/near-expiry tokens and keeps fresh ones. **Before 
merge:** exercise the full GAQ flow (polling + `ws` transport) across a 
token-refresh boundary.
   
   ### ADDITIONAL INFORMATION
   
   - [ ] Has associated issue:
   - [ ] Required feature flags: GLOBAL_ASYNC_QUERIES
   - [ ] Changes UI
   - [ ] Includes DB Migration
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


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