diff --git a/src/main/java/sh/libre/scim/core/ScimClient.java b/src/main/java/sh/libre/scim/core/ScimClient.java index daaa4b00a3b5ea26501f7dfa5caefed62e7858cf..6fa956353dcc18187651980d4a71a16b6dfef496 100644 --- a/src/main/java/sh/libre/scim/core/ScimClient.java +++ b/src/main/java/sh/libre/scim/core/ScimClient.java @@ -32,9 +32,11 @@ public class ScimClient { final private RetryRegistry registry; final private String name; final private KeycloakSession session; + final private String contentType; - public ScimClient(String name, String url, KeycloakSession session) { + public ScimClient(String name, String url, String contentType, KeycloakSession session) { this.name = name; + this.contentType = contentType; this.session = session; var target = client.target(url); @@ -61,12 +63,13 @@ public class ScimClient { var retry = registry.retry("create-" + kcUser.getId()); var spUser = retry.executeSupplier(() -> { try { - return scimService.create("Users", user); + return scimService.createRequest("Users", user).contentType(contentType).invoke(); } catch (ScimException e) { throw new RuntimeException(e); } }); var scimUser = toScimUser(spUser); + scimUser.setLocalId(kcUser.getId()); getEM().persist(scimUser); } @@ -83,7 +86,7 @@ public class ScimClient { var retry = registry.retry("replace-" + kcUser.getId()); retry.executeSupplier(() -> { try { - return scimService.replace(user); + return scimService.replaceRequest(user).contentType(contentType).invoke(); } catch (ScimException e) { throw new RuntimeException(e); } @@ -102,7 +105,7 @@ public class ScimClient { var retry = registry.retry("delete-" + userId); retry.executeSupplier(() -> { try { - scimService.delete("Users", resource.getRemoteId()); + scimService.deleteRequest("Users", resource.getRemoteId()).contentType(contentType).invoke(); } catch (ScimException e) { throw new RuntimeException(e); } @@ -149,6 +152,7 @@ public class ScimClient { name.setGivenName(kcUser.getFirstName()); name.setFamilyName(kcUser.getLastName()); user.setName(name); + user.setDisplayName(kcUser.getFirstName() + " " + kcUser.getLastName()); var emails = new ArrayList<Email>(); if (kcUser.getEmail() != "") { @@ -156,6 +160,7 @@ public class ScimClient { emails.add(email); } user.setEmails(emails); + user.setActive(kcUser.isEnabled()); return user; } diff --git a/src/main/java/sh/libre/scim/core/ScimDispatcher.java b/src/main/java/sh/libre/scim/core/ScimDispatcher.java index 178976ab844aaf46ecee40938ab20a7a1131993d..ea6a763b320996cc915c70b6b6e9c8793354d111 100644 --- a/src/main/java/sh/libre/scim/core/ScimDispatcher.java +++ b/src/main/java/sh/libre/scim/core/ScimDispatcher.java @@ -17,11 +17,11 @@ public class ScimDispatcher { public void run(Consumer<ScimClient> f) { session.getContext().getRealm().getComponentsStream() .filter((m) -> { - return ScimStorageProviderFactory.ID.equals(m.getProviderId()); + return ScimStorageProviderFactory.ID.equals(m.getProviderId()) && m.get("enabled").equals("true"); }) .forEach(m -> { LOGGER.infof("%s %s %s %s", m.getId(), m.getName(), m.getProviderId(), m.getProviderType()); - var client = new ScimClient(m.getName(), m.get("endpoint"), session); + var client = new ScimClient(m.getName(), m.get("endpoint"), m.get("content-type"), session); try { f.accept(client); } finally { diff --git a/src/main/java/sh/libre/scim/storage/ScimStorageProviderFactory.java b/src/main/java/sh/libre/scim/storage/ScimStorageProviderFactory.java index d9a9b57f52b20a40ec81acb88247e87ab32d07f4..57cfc2deac5a3018c689f084fd7f04d499e3e434 100644 --- a/src/main/java/sh/libre/scim/storage/ScimStorageProviderFactory.java +++ b/src/main/java/sh/libre/scim/storage/ScimStorageProviderFactory.java @@ -2,6 +2,10 @@ package sh.libre.scim.storage; import java.util.List; +import javax.ws.rs.core.MediaType; + +import com.unboundid.scim2.client.ScimService; + import org.keycloak.component.ComponentModel; import org.keycloak.models.KeycloakSession; import org.keycloak.provider.ProviderConfigProperty; @@ -20,6 +24,14 @@ public class ScimStorageProviderFactory implements UserStorageProviderFactory<Sc .helpText("External SCIM 2.0 base " + "URL (/ServiceProviderConfig /Schemas and /ResourcesTypes should be accessible)") .add() + .property() + .name("content-type") + .type(ProviderConfigProperty.LIST_TYPE) + .label("Endpoint content type") + .helpText("Only used when endpoint doesn't support application/scim+json") + .options(MediaType.APPLICATION_JSON.toString(), ScimService.MEDIA_TYPE_SCIM_TYPE.toString()) + .defaultValue(ScimService.MEDIA_TYPE_SCIM_TYPE.toString()) + .add() .build(); }