tju-yxq opened a new issue, #5303:
URL: https://github.com/apache/rocketmq-dashboard/issues/5303

   ## Problem
   
   A Studio session token stays valid until its **absolute** expiry — 24 hours 
by default — no matter how long it goes unused. An operator who signs in Monday 
morning and closes the browser two minutes later leaves a token behind that 
still authenticates API calls until Tuesday morning. If that token leaks out of 
a shared workstation, a browser profile, a screenshot of devtools or a log 
line, the attacker has a working credential for up to a day with zero activity 
required to keep it alive. This is a console that manages production brokers, 
ACLs, cloud credentials and message contents; the standard control for that 
class of surface is an idle-session deadline, and it is missing.
   
   The console already has all the observability for this: it tracks 
`last_seen_at` per session, refreshes it on authenticated requests (throttled 
to one write per 5 minutes), classifies sessions as "stale" after 15 unused 
minutes, shows per-session idle seconds in the user management drawer, and 
reports a stale-session count on the overview. A stale session is still fully 
authenticated — the classification is purely informational.
   
   ## Current behavior and reproduction
   
   1. Sign in to Studio; note the session timeout setting (default 1440 
minutes, range 5–1440).
   2. Copy the `Bearer` token from the browser (devtools → local storage / 
network tab).
   3. Leave it untouched for an hour, a day — any period shorter than the 
absolute expiry.
   4. Call any API with the token: it is still accepted. Nothing about 
inactivity ever invalidates it.
   5. As an administrator, open **User Management**: the session sits in the 
drawer marked "长时间未活跃" (stale) — and remains usable indefinitely until its 
absolute expiry.
   
   `server/src/main/java/org/apache/rocketmq/studio/auth/AuthService.java` 
(around lines 71-76) defines only the absolute window:
   
   ```java
   private static final int DEFAULT_SESSION_TIMEOUT_MINUTES = 1440;
   private static final int MIN_SESSION_TIMEOUT_MINUTES = 5;
   private static final int MAX_SESSION_TIMEOUT_MINUTES = 1440;
   private static final Duration LAST_SEEN_UPDATE_INTERVAL = 
Duration.ofMinutes(5);
   private static final Duration STALE_SESSION_THRESHOLD = 
Duration.ofMinutes(15);
   ```
   
   And the token validation path (around line 439) checks revocation and 
absolute expiry only:
   
   ```java
   RmqStudioSession session = sessionMapper.selectOne(new 
QueryWrapper<RmqStudioSession>()
           .eq("token_hash", tokenHash(token)));
   if (session == null || session.getRevokedAt() != null || 
!session.getExpiresAt().isAfter(now())) {
       return Optional.empty();
   }
   ```
   
   `last_seen_at` is read afterwards solely to decide whether the throttled 
refresh write is due. The in-memory (properties-based) mode tracks even less: 
`AuthSession` holds only the user and `expiresAtMillis`.
   
   ## Proposed behavior
   
   - A configurable **session idle timeout** in general settings, next to the 
existing session timeout: minutes a token may stay unused before its session is 
treated as expired.
   - Default **30 minutes**; **0** is the explicit opt-out (absolute expiry 
only); values 1–9 resolve as 10 — above the 5-minute last-seen write throttle, 
so an active session's throttled writes can never lag enough to idle it out 
falsely.
   - A session that idles out is **revoked** (`revoked_at = now`) the next time 
its token is presented, and the scheduled session cleanup (every 5 minutes) 
also revokes idle-expired rows so the active-session views stay truthful even 
when the abandoned token is never presented again. Rows are still removed at 
absolute expiry as today.
   - Sessions written before `last_seen_at` existed (NULL) keep the absolute 
deadline as their only deadline.
   - The in-memory mode tracks last-seen per token and enforces the same window.
   - Saves from clients that predate the field keep the stored value instead of 
resetting it; the existing absolute timeout behavior is unchanged.
   
   ## Acceptance criteria
   
   - [ ] A token unused longer than the configured idle window is rejected and 
its session row revoked, while its absolute expiry is still in the future.
   - [ ] A session used within the window stays authenticated and its 
`last_seen_at` keeps refreshing.
   - [ ] Idle timeout 0 disables the deadline (absolute expiry only).
   - [ ] Values 1–9 resolve as 10; values above 1440 fall back to the default, 
mirroring the absolute timeout's defensive clamp.
   - [ ] Sessions with NULL `last_seen_at` are never idle-revoked.
   - [ ] The scheduled cleanup revokes idle-expired sessions within one 
interval and still deletes absolutely-expired rows.
   - [ ] The settings page exposes the field next to the session timeout with 
Chinese and English help text; saving persists it and out-of-range submissions 
are rejected.
   - [ ] Saves from clients that omit the field do not reset a configured value.
   - [ ] Existing absolute-timeout behavior is unchanged.
   
   ## Importance
   
   Must-have. This is the standard control for an operational console with 
production-broker, ACL and credential access; the repo already treats login 
hardening (lockouts, uniform 401s, disabled-account hiding) as default-on. The 
current workaround — shortening the absolute session timeout to 5 minutes — 
punishes every active user with a re-login every 5 minutes while still granting 
a leaked token that full window; it does not actually constrain inactivity.
   
   ## Duplicate check
   
   Searched open and closed issues and PRs for `idle session`, `session 
timeout`, `inactive session revoke`, and `idle timeout`. The closest items are 
#1002 (persisted session settings taking effect — about settings plumbing, not 
an idle deadline) and #2650 (merged production hardening — caching/pool/asset 
topics, no session idleness). Nothing proposes or implements an idle-session 
deadline.
   


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

Reply via email to