Connection Limit (Concurrent Session Limit) ¶
1. Purpose and Scope ¶
- This section defines the requirements for limiting concurrent MCT sessions to reduce the risk of unauthorized access from excessive active sessions.
- Support STIG compliance with AC-10-00.
MCT limits concurrent sessions by tracking active login tokens per user in Redis. When a user exceeds the allowed session limit, the oldest active session is superseded and evicted by FIFO order.
2. Concurrent Session Limits ¶
Session limits are based on the user's privilege level.
| Access level | Max concurrent sessions |
|---|---|
| Privileged access | 3 |
| Non-privileged access | 2 |
Privileged users are allowed up to 3 concurrent sessions. Non-privileged users are allowed up to 2 concurrent sessions.
3. Redis Session Tracking ¶
SessionManagerServiceImpl stores token hashes in Redis instead of raw tokens.
| Redis key | Type | Description |
|---|---|---|
mct:active_sessions:{username} | ZSET | Tracks active sessions for a user. The score is the registration timestamp and the member is the token hash. |
mct:superseded_sessions:{tokenHash} | String | Stores the username with TTL for fast superseded-token lookup. |
Tokens are hashed with SHA-256 before storage to avoid persisting raw tokens in Redis.
4. Session Management Flow ¶
4.1 Session registration on login ¶
When a user logs in, SessionManagerServiceImpl registers the current token and enforces the configured session limit.
public void handleUserLoginSession(Member member)
The registration flow is:
- Extract the current
Authorization: Bearertoken from the activeHttpServletRequestthroughAcUtil. - Determine the max session limit based on the member privilege level.
- Clean up expired sessions by removing stale token hashes whose session keys no longer exist.
- Add the current token hash to the user's Redis ZSET with the current timestamp as the score.
- If the active session count exceeds the max limit, evict the oldest token by the lowest ZSET score.
- Register the evicted token in the superseded-session list with TTL.
- Set a 24-hour expiration on the user's active-session tracking key for cleanup.
4.2 Superseded-token validation ¶
StatusService exposes a lightweight validation endpoint that checks Redis without going through SSO verification.
GET /status/validate
Authorization: Bearer {token}
Valid response:
{
"valid": true
}
Superseded response:
{
"valid": false,
"reason": "Your session has been superseded by a new login."
}
The frontend polls this endpoint to detect whether the current session has been evicted. Once evicted, the frontend displays a "Session Superseded" dialog.
5. Eviction Sequence ¶
sequenceDiagram
participant User as Admin user
participant Session as SessionManagerServiceImpl
participant Redis as Redis
participant Auth as AuthAspect
Note over User,Redis: Active sessions are token1, token2, and token3
User->>Session: Login again and obtain token4
Session->>Redis: Clean up expired sessions
Session->>Redis: Check active session count
Session->>Redis: Evict token1 as the oldest session
Session->>Redis: Register token4
Note over Redis: Active sessions are token2, token3, and token4
User->>Auth: token1 holder starts a protected operation
Auth->>Redis: Check whether token1 is still active
Redis-->>Auth: token1 is superseded
Auth-->>User: 401 Unauthorized
6. Design Highlights ¶
- New logins succeed and the oldest session is evicted instead of rejecting the new login.
- Repeated requests with the same token, such as page refreshes, do not trigger duplicate registration.
- Session keys have TTL, and stale ZSET entries are cleaned up during registration.
- Superseded-token lookup is Redis-based and does not require an additional SSO verification call.