diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index e2d97ec..99faf6b 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -1689,7 +1690,7 @@ public class RepresentationToModel {
model.setName(rep.getName());
model.setIdentityProviderAlias(rep.getIdentityProviderAlias());
model.setIdentityProviderMapper(rep.getIdentityProviderMapper());
- model.setConfig(rep.getConfig());
+ model.setConfig(removeEmptyString(rep.getConfig()));
return model;
}
@@ -2437,4 +2438,20 @@ public class RepresentationToModel {
}
}
+
+ private static Map<String, String> removeEmptyString(Map<String, String> map) {
+ if (map == null) {
+ return null;
+ }
+
+ Map<String, String> m = new HashMap<>(map);
+ for (Iterator<Map.Entry<String, String>> itr = m.entrySet().iterator(); itr.hasNext(); ) {
+ Map.Entry<String, String> e = itr.next();
+ if (e.getValue() == null || e.getValue().equals("")) {
+ itr.remove();
+ }
+ }
+ return m;
+ }
+
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
index d953847..fdf0c14 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
@@ -23,6 +23,7 @@ import org.keycloak.admin.client.resource.IdentityProviderResource;
import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
+import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
import org.keycloak.events.admin.OperationType;
@@ -30,7 +31,6 @@ import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.utils.StripSecretsUtils;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.ComponentRepresentation;
-import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
import org.keycloak.representations.idm.IdentityProviderMapperTypeRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
@@ -39,10 +39,12 @@ import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntityDescriptorParser;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.util.AdminEventPaths;
+import org.w3c.dom.NodeList;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.xml.crypto.dsig.XMLSignature;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
@@ -57,16 +59,17 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.xml.crypto.dsig.XMLSignature;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.hamcrest.Matchers.*;
-import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
-import org.w3c.dom.NodeList;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -449,6 +452,40 @@ public class IdentityProviderTest extends AbstractAdminTest {
}
}
+ // KEYCLOAK-4962
+ @Test
+ public void testUpdateProtocolMappers() {
+ create(createRep("google", "google"));
+
+ IdentityProviderResource provider = realm.identityProviders().get("google");
+
+ IdentityProviderMapperRepresentation mapper = new IdentityProviderMapperRepresentation();
+ mapper.setIdentityProviderAlias("google");
+ mapper.setName("my_mapper");
+ mapper.setIdentityProviderMapper("oidc-hardcoded-role-idp-mapper");
+ Map<String, String> config = new HashMap<>();
+ config.put("role", "");
+ mapper.setConfig(config);
+
+ Response response = provider.addMapper(mapper);
+ String mapperId = ApiUtil.getCreatedId(response);
+
+
+ List<IdentityProviderMapperRepresentation> mappers = provider.getMappers();
+ assertEquals(1, mappers.size());
+ assertEquals(0, mappers.get(0).getConfig().size());
+
+ mapper = provider.getMapperById(mapperId);
+ mapper.getConfig().put("role", "offline_access");
+
+ provider.update(mapperId, mapper);
+
+ mappers = provider.getMappers();
+ assertEquals(1, mappers.size());
+ assertEquals(1, mappers.get(0).getConfig().size());
+ assertEquals("offline_access", mappers.get(0).getConfig().get("role"));
+ }
+
@Test
public void testInstalledIdentityProviders() {
Response response = realm.identityProviders().getIdentityProviders("oidc");