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]