Release 1.6.0#99
Open
nicolamacoir wants to merge 53 commits into
Open
Conversation
…s. refactored the code to simplify/share a bit.
- Introduced SCIM_IDENTITY_PROVIDER_ALIAS. - Updated kc-test.json to include unmanagedAttributePolicy and custom attributes. - Enhanced MetadataController to handle custom attributes based on identity provider mappers. - Updated tests to validate provisioning and patching of custom attributes.
docs: update installation instructions in README.md for GitHub Release
…ternal-token-validation Improve logging
Added basic auth for okta compatibility
# Conflicts: # src/main/java/fi/metatavu/keycloak/scim/server/organization/OrganizationController.java
…ustom-user-attributes
…dundant session storage - Remove organizationType from ScimResources, ScimRealmResourceProvider, and ScimRealmResourceProviderFactory. The default OrganizationScimServerProvider is resolved via session.getProvider() without a provider ID. Implementors can override using KC_SPI_ORGANIZATION_SCIM_SERVER_PROVIDER__PROVIDER_DEFAULT. - Lazy-initialize OrganizationScimServer in ScimResources to avoid failing all SCIM endpoints (including realm-level) when the org provider is missing or misconfigured. Includes null guard and try/catch with warning. - Remove redundant session field from KeycloakOrganizationScimServerProvider (was stored but never read, since createScimContext is static). - Remove redundant session field from OrganizationScimServer (methods use scimContext.getSession() instead). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: phasetwo orgs implementation
RFC 7644 §3.5.2 allows PATCH operations to omit 'path' and carry the
attribute changes inside a map-valued 'value'. Okta's Deactivate User
flow uses this exact shape:
{"op":"replace","value":{"active":false}}
UsersController.patchUser previously called findByScimPath(null) on this
shape, got null back, and threw UnsupportedUserPath, returning HTTP 500
without applying any state change.
This change handles the path-less shape by iterating the map-valued
'value' and applying each entry as a separate attribute update, sharing
the write logic with the with-path branch via a new private
applyPatchValue helper.
Test: RealmUserPatchTestsIT#testDeactivateUserPathLessPatchOp covers
both deactivate and reactivate through the path-less shape.
Fixes #95
Handle path-less PatchOp shape (Okta Deactivate User)
Three closely-related fixes that together let Okta-driven SCIM Group
Push and User provisioning round-trip through the realm and
organization-scoped endpoints.
1. Path-less PatchOp on Groups. RFC 7644 §3.5.2 says that when "path"
is omitted on a PatchOp, "value" carries a map of attribute -> value
to apply to the resource. Okta's Group Push (add / remove members)
emits this shape:
{"op":"replace","value":{"members":[{"value":"<user-id>"}]}}
The previous code called findByScimPath(null), got null, and threw
UnsupportedGroupPath, breaking every Okta Group Push. A path-less
branch in patchGroup expands the map into one logical operation per
entry.
2. Valid JSON error bodies on every patch / create / update / delete
path. Per RFC 7644 §3.12 a SCIM Service Provider error response is
a JSON object with schemas, status, and detail. Several handlers
were returning plain-text strings, which Okta surfaces in its
System Log as a malformed JSON parsing error and which other SCIM
clients reject before showing the operator anything useful. A new
ScimErrors helper centralises the envelope and is wired into the
Groups, Users, OrganizationUser, RealmScimServer, and
OrganizationScimServer entry points.
3. Silently ignore read-only / structural attrs on PATCH. Per RFC 7644
§3.5.2 and the SCIM core schema (RFC 7643 §3.1), servers MUST not
error on read-only / structural attributes appearing in PATCH
payloads. Okta and other clients echo "id", "meta", and "schemas"
inside the PatchOp value when it is constructed from a prior GET.
isReadOnlyOrStructural lives on AbstractController and is
consulted in both path-less and path-based branches before
attribute resolution. externalId is intentionally NOT in the list
per RFC 7643 §3.1 (client-settable).
Test assertions in *ListTestsIT switched from assertEquals on the
exact pre-change plain-text error string to assertTrue substring on
"Invalid filter", so they remain correct regardless of whether the
body is plain text or JSON.
Contributor
|
Would ❤️ to see a release that includes the recent updates. Please let me know if there's anything I can do to help. |
GroupsController.dispatchGroupMembershipLeaveEvent passed user.getEmail() directly into Map.of(), which rejects null values and threw NullPointerException whenever the removed member had no email set in Keycloak. PATCH /Groups remove-member then returned HTTP 500 to the client. The sibling join event already coalesces null to "" — apply the same guard to the leave event so the two paths stay symmetric. Adds a regression test that creates a user, clears their email via the Keycloak admin client, then removes them from a group via SCIM PATCH and asserts success. Closes #103
… /Users
Two related problems on POST /Users when the request collides with an
existing user:
- The realm-scope createUser pre-checked only username, returning a
generic "User already exists" body that did not identify the offending
field. A duplicate email was not pre-checked, so the create reached
UserModel.setEmail and surfaced as Keycloak's generic
{"error":"unknown_error"} response.
- The organization-scope createUser had no pre-check at all — both
collisions surfaced as unknown_error.
Add a getUserByUsername + getUserByEmail pre-check on both scopes and
return a 409 with a body that identifies the duplicated field and value:
User already exists with username: <X>
User already exists with email: <X>
The email pre-check is gated on RealmModel.isDuplicateEmailsAllowed so
realms configured to permit duplicate emails still create successfully.
Adds regression tests for both the duplicate-username and the
duplicate-email cases on both scopes; existing duplicate-username tests
are strengthened to assert the message identifies the field.
Out of scope: Keycloak's user-profile email validator can still reject
duplicates even when the realm flag is on. That path would need a
ModelDuplicateException catch in the controller layer and is left for a
follow-up.
Closes #109
…email fix: guard null email in group membership leave admin event
… on USER_PROFILE attrs Promote UsersController.applyPatchValue to protected and delete the near-identical OrganizationUserController.applyOrgPatchValue, routing both controllers through the single shared method. Add UserAttribute.clear(UserModel) with an optional Consumer<UserModel> remover registered at construction time. USER_PROFILE-backed attributes (externalId, displayName, etc.) register user -> user.removeAttribute(name) so REMOVE operations no longer pass null into List.of(value), which threw NPE on Java 9+ and returned HTTP 500.
# Conflicts: # src/test/java/fi/metatavu/keycloak/scim/server/test/tests/functional/RealmGroupPatchTestsIT.java
… support for custom attributes
…ttributes Add Support for Custom User Attributes in SCIM Provisioning
|
Handle path-less PatchOp on Groups + return valid JSON errors
|
…nScimServer Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The duplicate-username and duplicate-email conflict tests added in 02a11e9 used assertTrue without importing it, breaking compileTestJava. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rrors fix: surface duplicate-username and duplicate-email conflicts on POST /Users
|
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.



Merging recent change from develop to master in order to create a next release