Repository navigation
Fix SCIM unfiltered search returning non-imported federated users - #51683
Conversation
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Aligns SCIM /Users list semantics to exclude non-imported federated users (e.g., LDAP/custom providers with import disabled), fixing inconsistent results between filtered vs. unfiltered searches and documenting the expected behavior.
Changes:
- Update SCIM user listing/counting to query local storage only for unfiltered searches.
- Add an integration test covering filtered vs. unfiltered search consistency with non-imported federated users.
- Document SCIM
/Usersbehavior and add test dependency needed for the custom federation provider.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| scim/model/src/main/java/org/keycloak/scim/model/user/UserResourceTypeProvider.java | Ensures unfiltered SCIM user search/count uses local storage, excluding non-imported federated users. |
| scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/FederatedUserTest.java | Adds regression test verifying consistent filtered/unfiltered results and exclusion of non-imported federated users. |
| scim/tests/base/pom.xml | Adds test-scoped dependency required by the new integration test. |
| docs/documentation/server_admin/topics/scim/managing-users.adoc | Documents that SCIM /Users returns only locally stored users and excludes non-imported federated users. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
a7ac047 to
0e6d75c
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (3)
scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/FederatedUserTest.java:62
- This comment is no longer true after the change: the unfiltered request now uses local storage and does not include federated-provider results. Update it to describe the expected fixed path.
// unfiltered SCIM search - goes through UserStorageManager, includes federated providers
scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/FederatedUserTest.java:84
not(hasItems(a, b))passes when either one of the two users is present; it only rejects a list containing both. Assert each forbidden username separately so a partial leak cannot satisfy this regression test.
assertThat(unfilteredUserNames, not(hasItems("fed-charlie", "fed-diana")));
assertThat(filteredUserNames, not(hasItems("fed-charlie", "fed-diana")));
scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/FederatedUserTest.java:46
- This describes the pre-fix implementation as the current behavior, but the production change now routes unfiltered searches to local storage. Phrase it as historical regression context so the test documentation remains accurate.
This issue also appears on line 62 of the same file.
* Currently, unfiltered searches go through UserStorageManager (which queries
* federated providers), while filtered searches use direct JPA queries against
* the local UserEntity table - so non-imported federated users only appear in
* unfiltered results.
0e6d75c to
0709242
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Suppressed comments (3)
scim/model/src/main/java/org/keycloak/scim/model/user/UserResourceTypeProvider.java:41
- This introduces a dependency on
UserStoragePrivateUtil(a private/internal utility). That makes SCIM more sensitive to internal refactors in user storage. If there is an existing supported accessor for local user storage in this layer, prefer that; otherwise consider encapsulating the local-only lookup behind a small SCIM-local helper (or extending the SCIM/user SPI to express ‘local-only’ intent) so the private util isn’t referenced directly throughout resource type providers.
import org.keycloak.storage.UserStoragePrivateUtil;
scim/model/src/main/java/org/keycloak/scim/model/user/UserResourceTypeProvider.java:155
- This introduces a dependency on
UserStoragePrivateUtil(a private/internal utility). That makes SCIM more sensitive to internal refactors in user storage. If there is an existing supported accessor for local user storage in this layer, prefer that; otherwise consider encapsulating the local-only lookup behind a small SCIM-local helper (or extending the SCIM/user SPI to express ‘local-only’ intent) so the private util isn’t referenced directly throughout resource type providers.
return UserStoragePrivateUtil.userLocalStorage(session).searchForUserStream(realm, Map.of(UserModel.INCLUDE_SERVICE_ACCOUNT, "false"), firstResult, maxResults);
scim/model/src/main/java/org/keycloak/scim/model/user/UserResourceTypeProvider.java:174
- This introduces a dependency on
UserStoragePrivateUtil(a private/internal utility). That makes SCIM more sensitive to internal refactors in user storage. If there is an existing supported accessor for local user storage in this layer, prefer that; otherwise consider encapsulating the local-only lookup behind a small SCIM-local helper (or extending the SCIM/user SPI to express ‘local-only’ intent) so the private util isn’t referenced directly throughout resource type providers.
return (long) UserStoragePrivateUtil.userLocalStorage(session).getUsersCount(realm, false);
pedroigor
left a comment
There was a problem hiding this comment.
I guess we also want to cover GET by ID?
0709242 to
f625976
Compare
Yes, I've updated the commit. |
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.federation.ldap.LDAPUserLoginTest#loginLDAPUserAuthenticationSimpleEncryptionStartTLSKeycloak CI - Java Distribution IT (windows-latest - temurin - 17) |
f625976 to
0555571
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (1)
scim/model/src/main/java/org/keycloak/scim/model/user/UserResourceTypeProvider.java:104
- Returning the local adapter directly bypasses
UserStorageManagervalidation for imported federated users. For example, a user linked to a removed provider remains readable and updatable here instead of being rejected, and a disabled provider's read-only delegate is skipped; first prove that a local row exists, then resolve it throughsession.users()to preserve federation validation without exposing non-imported users.
UserModel model = UserStoragePrivateUtil.userLocalStorage(session).getUserById(realm, id);
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.federation.ldap.LDAPUserLoginTest#loginLDAPUserAuthenticationSimpleEncryptionStartTLSKeycloak CI - Java Distribution IT (windows-latest - temurin - 17) |
Closes keycloak#51343 Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
0555571 to
1eacd4d
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (1)
scim/model/src/main/java/org/keycloak/scim/model/user/UserResourceTypeProvider.java:104
- Looking up the raw local adapter bypasses
UserStorageManager.validateUser, so imported users no longer receive their federation proxy/read-only delegate; SCIM PUT/PATCH can consequently update the local row even when the provider is read-only, and GET can return stale provider data. Reject provider-owned IDs first, then usesession.users()for local IDs so imported users retain normal federation validation and decoration.
UserModel model = UserStoragePrivateUtil.userLocalStorage(session).getUserById(realm, id);
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.webauthn.registration.WebAuthnOtherSettingsTest#timeout |
Closes #51343