Do not expose organization groups through the SCIM Users groups attribute - #51591
Merged
pedroigor merged 1 commit intoAug 11, 2026
Merged
Conversation
…bute Closes keycloak#51590 Signed-off-by: Sven-Torben Janus <sven-torben.janus@conciso.de>
Contributor
There was a problem hiding this comment.
Pull request overview
Prevents organization-related groups from appearing in SCIM user group attributes.
Changes:
- Filters organization groups during user serialization.
- Reuses the same predicate for user group write validation.
- Adds regression coverage for realm, organization, and backing groups.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
AbstractUserModelSchema.java |
Excludes organization groups from serialized memberships. |
UserCoreModelSchema.java |
Reuses the organization-group predicate. |
UserTest.java |
Verifies only realm groups are returned. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
pedroigor
approved these changes
Aug 11, 2026
pedroigor
left a comment
Contributor
There was a problem hiding this comment.
Thanks, @sventorben ! Created #51614 as a follow-up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #51590
Organization groups — and the organization's internal backing group — were exposed through the
groupsattribute of the SCIMUsersresource.AbstractUserModelSchema.getAttributeValuereturnedmodel.getGroupsStream()filtered only bycanViewGroup, which resolves toGroupPermissionsV2.canView(group)and short-circuits totruefor any caller holdingview-usersormanage-users. There was no group-type check on that path. Since organization membership is itself a membership in the organization's internal group, both that group and any organization groups were returned.The same boundary is already enforced for the
Groupsresource (#50310 / #50311) and on the SCIM user write path inUserCoreModelSchema.checkGroupMembershipPermission, which throws"Cannot access organization related group via non Organization API.". This aligns the read path with those.The predicate used by the write path is extracted into
AbstractUserModelSchema.isOrganizationGroupand reused on both sides, so the two cannot drift apart. It matches the existing behaviour exactly (Type.ORGANIZATIONand a non-null organization); both the internal group and organization groups carry the organization relationship, set inJpaOrganizationProvideron organization creation and increateGrouprespectively.Added
UserTest#testOrganizationGroupsNotExposedOnUser, which puts a user in a realm group, an organization, and an organization group, then asserts that only the realm group is returned byGET /Users/{id}?attributes=groups.Note for reviewers:
UserResourceTypeProvider.getAttributeExpressionmaps the SCIMgroupsfilter ontoUserGroupMembershipEntity.groupIdwithout a type restriction, so a user can still be filtered by a known organization group id. That is a separate surface from serialization and is left out of this change — happy to follow up if you would like it covered here or in its own issue.