Skip to content

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:

  1. Extract the current Authorization: Bearer token from the active HttpServletRequest through AcUtil.
  2. Determine the max session limit based on the member privilege level.
  3. Clean up expired sessions by removing stale token hashes whose session keys no longer exist.
  4. Add the current token hash to the user's Redis ZSET with the current timestamp as the score.
  5. If the active session count exceeds the max limit, evict the oldest token by the lowest ZSET score.
  6. Register the evicted token in the superseded-session list with TTL.
  7. 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.

Reference