Skip to content

feat: implement configurable concurrent session limits per user and client#3964

Open
mshipkovenski wants to merge 2 commits into
cloudfoundry:developfrom
mshipkovenski:feature/session-limits-concurrent
Open

feat: implement configurable concurrent session limits per user and client#3964
mshipkovenski wants to merge 2 commits into
cloudfoundry:developfrom
mshipkovenski:feature/session-limits-concurrent

Conversation

@mshipkovenski

Copy link
Copy Markdown

Introduce numeric concurrent session limits for refresh tokens, replacing the previous binary refreshTokenUnique flag with a numeric cap.

Key changes:

  • TokenPolicy: the internal refreshTokenUnique field is now an int (positive value = max sessions, -1 = unlimited). The original boolean getters/setters (isRefreshTokenUnique / setRefreshTokenUnique) are preserved with @JsonIgnore for backwards compatibility. New getMaxSessionLimit / setMaxSessionLimit accessors operate on the integer value. The @JsonSetter accepts boolean or integer input so existing configurations continue to work.

  • ClientConstants: adds a REFRESH_TOKEN_UNIQUE constant for the additionalInformation key used for per-client overrides.

  • OauthEndpointBeanConfiguration: the jwt.token.refresh.unique property now accepts both boolean strings ("true"/"false") and positive integers, parsed at startup.

  • UaaTokenServices: replaces the all-or-nothing deleteRefreshTokensForClientAndUserId call with enforceConcurrentSessionLimit, which revokes only the oldest tokens when the active count would exceed the configured limit. A per-client override (stored in additionalInformation) takes precedence over the zone-level policy. Rotation-aware: token reuse and token replacement are detected to avoid counting a refresh as a new session.

  • SampleIdentityZone.json: refreshTokenUnique serialises as -1 (integer) instead of false to reflect the new type.

  • Tests: DeprecatedUaaTokenServicesTests, RefreshRotationTest, TokenPolicyTest, and the IdentityZone endpoint tests are updated to cover the new behaviour, including per-user isolation, public-client rotation, and confidential-client JTI-reuse scenarios.

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jun 24, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: mshipkovenski / name: Miroslav Shipkovenski (593b9e1)

…lient

Introduce numeric concurrent session limits for refresh tokens, replacing
the previous binary refreshTokenUnique flag with a numeric cap.

Key changes:

- TokenPolicy: the internal `refreshTokenUnique` field is now an `int`
  (positive value = max sessions, -1 = unlimited). The original boolean
  getters/setters (`isRefreshTokenUnique` / `setRefreshTokenUnique`) are
  preserved with @JsonIgnore for backwards compatibility. New
  `getMaxSessionLimit` / `setMaxSessionLimit` accessors operate on the
  integer value. The @JsonSetter accepts boolean or integer input so
  existing configurations continue to work.

- ClientConstants: adds a REFRESH_TOKEN_UNIQUE constant for the
  additionalInformation key used for per-client overrides.

- OauthEndpointBeanConfiguration: the `jwt.token.refresh.unique` property
  now accepts both boolean strings ("true"/"false") and positive integers,
  parsed at startup.

- UaaTokenServices: replaces the all-or-nothing
  `deleteRefreshTokensForClientAndUserId` call with
  `enforceConcurrentSessionLimit`, which revokes only the oldest tokens
  when the active count would exceed the configured limit. A per-client
  override (stored in additionalInformation) takes precedence over the
  zone-level policy. Rotation-aware: token reuse and token replacement are
  detected to avoid counting a refresh as a new session.

- SampleIdentityZone.json: `refreshTokenUnique` serialises as -1 (integer)
  instead of false to reflect the new type.

- Tests: DeprecatedUaaTokenServicesTests, RefreshRotationTest, TokenPolicyTest,
  and the IdentityZone endpoint tests are updated to cover the new behaviour,
  including per-user isolation, public-client rotation, and confidential-client
  JTI-reuse scenarios.

Co-authored-by: Cursor <cursoragent@cursor.com>

ai-assisted=yes
@mshipkovenski mshipkovenski force-pushed the feature/session-limits-concurrent branch from db894b6 to 593b9e1 Compare June 24, 2026 19:54
@strehle strehle requested a review from Copilot June 25, 2026 14:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@fhanik

fhanik commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Can you please update the configuration reference too: https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-Configuration-Reference.md#jwttokenrefreshunique

The property now accepts a boolean or a positive integer. Update the
configuration reference to document:

- Type change from boolean to boolean | integer
- Semantics: false/0 = no limit, true = 1 session, N = N concurrent sessions
- Prerequisite: jwt.token.revocable must also be true
- Per-client override via refreshTokenUnique in additionalInformation
- Example yaml snippet showing a limit of 2 concurrent sessions
- Links to related properties jwt.token.revocable and jwt.token.refresh.rotate

Co-authored-by: Cursor <cursoragent@cursor.com>

ai-assisted=yes
@mshipkovenski

Copy link
Copy Markdown
Author

Can you please update the configuration reference too: https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-Configuration-Reference.md#jwttokenrefreshunique

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

3 participants