SAML javascript protocol mapper: disable uploading scripts through admin console by default (#14293)
Closes #14292
This commit is contained in:
parent
869ccc82b2
commit
040e52cfd7
9 changed files with 269 additions and 6 deletions
|
@ -31,6 +31,8 @@ public class ScriptProviderDescriptor {
|
|||
public static final String POLICIES = "policies";
|
||||
public static final String MAPPERS = "mappers";
|
||||
|
||||
public static final String SAML_MAPPERS = "saml-mappers";
|
||||
|
||||
private Map<String, List<ScriptProviderMetadata>> providers = new HashMap<>();
|
||||
|
||||
@JsonUnwrapped
|
||||
|
@ -54,6 +56,11 @@ public class ScriptProviderDescriptor {
|
|||
providers.put(MAPPERS, metadata);
|
||||
}
|
||||
|
||||
@JsonSetter(SAML_MAPPERS)
|
||||
public void setSAMLMappers(List<ScriptProviderMetadata> metadata) {
|
||||
providers.put(SAML_MAPPERS, metadata);
|
||||
}
|
||||
|
||||
public void addAuthenticator(String name, String fileName) {
|
||||
addProvider(AUTHENTICATORS, name, fileName, null);
|
||||
}
|
||||
|
@ -76,4 +83,8 @@ public class ScriptProviderDescriptor {
|
|||
public void addMapper(String name, String fileName) {
|
||||
addProvider(MAPPERS, name, fileName, null);
|
||||
}
|
||||
|
||||
public void addSAMLMapper(String name, String fileName) {
|
||||
addProvider(SAML_MAPPERS, name, fileName, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAP
|
|||
import static org.keycloak.representations.provider.ScriptProviderDescriptor.POLICIES;
|
||||
import static org.keycloak.quarkus.runtime.Environment.getProviderFiles;
|
||||
import static org.keycloak.theme.ClasspathThemeProviderFactory.KEYCLOAK_THEMES_JSON;
|
||||
import static org.keycloak.representations.provider.ScriptProviderDescriptor.SAML_MAPPERS;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
|
@ -92,6 +93,7 @@ import org.keycloak.config.StorageOptions;
|
|||
import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||
import org.keycloak.connections.jpa.JpaConnectionSpi;
|
||||
import org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory;
|
||||
import org.keycloak.protocol.saml.mappers.DeployedScriptSAMLProtocolMapper;
|
||||
import org.keycloak.quarkus.runtime.QuarkusProfile;
|
||||
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.QuarkusPropertiesConfigSource;
|
||||
|
@ -174,6 +176,7 @@ class KeycloakProcessor {
|
|||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(AUTHENTICATORS, KeycloakProcessor::registerScriptAuthenticator);
|
||||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(POLICIES, KeycloakProcessor::registerScriptPolicy);
|
||||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(MAPPERS, KeycloakProcessor::registerScriptMapper);
|
||||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(SAML_MAPPERS, KeycloakProcessor::registerSAMLScriptMapper);
|
||||
}
|
||||
|
||||
private static ProviderFactory registerScriptAuthenticator(ScriptProviderMetadata metadata) {
|
||||
|
@ -188,6 +191,10 @@ class KeycloakProcessor {
|
|||
return new DeployedScriptOIDCProtocolMapper(metadata);
|
||||
}
|
||||
|
||||
private static ProviderFactory registerSAMLScriptMapper(ScriptProviderMetadata metadata) {
|
||||
return new DeployedScriptSAMLProtocolMapper(metadata);
|
||||
}
|
||||
|
||||
@BuildStep
|
||||
FeatureBuildItem getFeature() {
|
||||
return new FeatureBuildItem("keycloak");
|
||||
|
@ -679,7 +686,7 @@ class KeycloakProcessor {
|
|||
}
|
||||
|
||||
private boolean isScriptForSpi(Spi spi, String type) {
|
||||
if (spi instanceof ProtocolMapperSpi && MAPPERS.equals(type)) {
|
||||
if (spi instanceof ProtocolMapperSpi && (MAPPERS.equals(type) || SAML_MAPPERS.equals(type))) {
|
||||
return true;
|
||||
} else if (spi instanceof PolicySpi && POLICIES.equals(type)) {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package org.keycloak.protocol.saml.mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class DeployedScriptSAMLProtocolMapper extends ScriptBasedMapper {
|
||||
|
||||
protected ScriptProviderMetadata metadata;
|
||||
|
||||
public DeployedScriptSAMLProtocolMapper(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public DeployedScriptSAMLProtocolMapper() {
|
||||
// for reflection
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return metadata.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return metadata.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return metadata.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getScriptCode(ProtocolMapperModel mapperModel) {
|
||||
return metadata.getCode();
|
||||
}
|
||||
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return super.getConfigProperties().stream()
|
||||
.filter(providerConfigProperty -> !ProviderConfigProperty.SCRIPT_TYPE.equals(providerConfigProperty.getName())) // filter "script" property
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void setMetadata(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public ScriptProviderMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package org.keycloak.protocol.saml.mappers;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.protocol.ProtocolMapperConfigException;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.scripting.EvaluatableScriptAdapter;
|
||||
import org.keycloak.scripting.ScriptCompilationException;
|
||||
|
@ -20,7 +22,7 @@ import java.util.*;
|
|||
*
|
||||
* @author Alistair Doswald
|
||||
*/
|
||||
public class ScriptBasedMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
||||
public class ScriptBasedMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper, EnvironmentDependentProviderFactory {
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<>();
|
||||
public static final String PROVIDER_ID = "saml-javascript-mapper";
|
||||
|
@ -92,6 +94,11 @@ public class ScriptBasedMapper extends AbstractSAMLProtocolMapper implements SAM
|
|||
return "Evaluates a JavaScript function to produce an attribute value based on context information.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return Profile.isFeatureEnabled(Profile.Feature.SCRIPTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method attaches one or many attributes to the passed attribute statement.
|
||||
* To obtain the attribute values, it executes the mapper's script and returns attaches the returned value to the
|
||||
|
@ -110,7 +117,7 @@ public class ScriptBasedMapper extends AbstractSAMLProtocolMapper implements SAM
|
|||
KeycloakSession session, UserSessionModel userSession,
|
||||
AuthenticatedClientSessionModel clientSession) {
|
||||
UserModel user = userSession.getUser();
|
||||
String scriptSource = mappingModel.getConfig().get(ProviderConfigProperty.SCRIPT_TYPE);
|
||||
String scriptSource = getScriptCode(mappingModel);
|
||||
RealmModel realm = userSession.getRealm();
|
||||
|
||||
String single = mappingModel.getConfig().get(SINGLE_VALUE_ATTRIBUTE);
|
||||
|
@ -158,7 +165,7 @@ public class ScriptBasedMapper extends AbstractSAMLProtocolMapper implements SAM
|
|||
@Override
|
||||
public void validateConfig(KeycloakSession session, RealmModel realm, ProtocolMapperContainerModel client, ProtocolMapperModel mapperModel) throws ProtocolMapperConfigException {
|
||||
|
||||
String scriptCode = mapperModel.getConfig().get(ProviderConfigProperty.SCRIPT_TYPE);
|
||||
String scriptCode = getScriptCode(mapperModel);
|
||||
if (scriptCode == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -173,6 +180,10 @@ public class ScriptBasedMapper extends AbstractSAMLProtocolMapper implements SAM
|
|||
}
|
||||
}
|
||||
|
||||
protected String getScriptCode(ProtocolMapperModel mappingModel) {
|
||||
return mappingModel.getConfig().get(ProviderConfigProperty.SCRIPT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an protocol mapper model for the this script based mapper. This mapper model is meant to be used for
|
||||
* testing, as normally such objects are created in a different manner through the keycloak GUI.
|
||||
|
|
|
@ -36,7 +36,6 @@ org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
|
|||
org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
|
||||
org.keycloak.protocol.saml.mappers.UserSessionNoteStatementMapper
|
||||
org.keycloak.protocol.saml.mappers.GroupMembershipMapper
|
||||
org.keycloak.protocol.saml.mappers.ScriptBasedMapper
|
||||
org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper
|
||||
org.keycloak.protocol.oidc.mappers.UserRealmRoleMappingMapper
|
||||
org.keycloak.protocol.oidc.mappers.SHA256PairwiseSubMapper
|
||||
|
|
|
@ -52,7 +52,7 @@ public class TestCleanup {
|
|||
private final String realmName;
|
||||
private final ConcurrentLinkedDeque<Runnable> genericCleanups = new ConcurrentLinkedDeque<>();
|
||||
|
||||
// Key is kind of entity (eg. "client", "role", "user" etc), Values are all kind of entities of given type to cleanup
|
||||
// Key is kind of entity (eg. "client", "role", "user" etc), Values are all IDs of entities of given type to cleanup
|
||||
private final ConcurrentMultivaluedHashMap<String, String> entities = new ConcurrentMultivaluedHashMap<>();
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
package org.keycloak.testsuite.script;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.container.test.api.TargetsContainer;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.asset.StringAsset;
|
||||
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||
import org.keycloak.protocol.saml.SamlProtocol;
|
||||
import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
|
||||
import org.keycloak.protocol.saml.mappers.ScriptBasedMapper;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.provider.ScriptProviderDescriptor;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeatures;
|
||||
import org.keycloak.testsuite.saml.AbstractSamlTest;
|
||||
import org.keycloak.testsuite.saml.RoleMapperTest;
|
||||
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
||||
import org.keycloak.testsuite.updaters.ProtocolMappersUpdater;
|
||||
import org.keycloak.testsuite.util.ContainerAssume;
|
||||
import org.keycloak.testsuite.util.Matchers;
|
||||
import org.keycloak.testsuite.util.SamlClient;
|
||||
import org.keycloak.testsuite.util.SamlClientBuilder;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.keycloak.common.Profile.Feature.SCRIPTS;
|
||||
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
|
||||
import static org.keycloak.testsuite.saml.RoleMapperTest.createSamlProtocolMapper;
|
||||
import static org.keycloak.testsuite.util.SamlStreams.assertionsUnencrypted;
|
||||
import static org.keycloak.testsuite.util.SamlStreams.attributeStatements;
|
||||
import static org.keycloak.testsuite.util.SamlStreams.attributesUnecrypted;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class DeployedSAMLScriptMapperTest extends AbstractSamlTest {
|
||||
|
||||
private static final String SCRIPT_DEPLOYMENT_NAME = "scripts.jar";
|
||||
|
||||
private ClientAttributeUpdater cau;
|
||||
private ProtocolMappersUpdater pmu;
|
||||
|
||||
@Deployment(name = SCRIPT_DEPLOYMENT_NAME, managed = false, testable = false)
|
||||
@TargetsContainer(AUTH_SERVER_CURRENT)
|
||||
public static JavaArchive deploy() throws IOException {
|
||||
ScriptProviderDescriptor representation = new ScriptProviderDescriptor();
|
||||
|
||||
representation.addSAMLMapper("My Mapper", "mapper-a.js");
|
||||
|
||||
return ShrinkWrap.create(JavaArchive.class, SCRIPT_DEPLOYMENT_NAME)
|
||||
.addAsManifestResource(new StringAsset(JsonSerialization.writeValueAsPrettyString(representation)),
|
||||
"keycloak-scripts.json")
|
||||
.addAsResource("scripts/mapper-example.js", "mapper-a.js");
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void verifyEnvironment() {
|
||||
ContainerAssume.assumeNotAuthServerUndertow();
|
||||
}
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
@Before
|
||||
public void deployScripts() throws Exception {
|
||||
deployer.deploy(SCRIPT_DEPLOYMENT_NAME);
|
||||
reconnectAdminClient();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void cleanMappersAndScopes() {
|
||||
this.cau = ClientAttributeUpdater.forClient(adminClient, REALM_NAME, SAML_CLIENT_ID_EMPLOYEE_2)
|
||||
.setDefaultClientScopes(Collections.EMPTY_LIST)
|
||||
.update();
|
||||
this.pmu = cau.protocolMappers()
|
||||
.clear()
|
||||
.update();
|
||||
|
||||
getCleanup(REALM_NAME)
|
||||
.addCleanup(this.cau)
|
||||
.addCleanup(this.pmu);
|
||||
}
|
||||
|
||||
@After
|
||||
public void onAfter() throws Exception {
|
||||
deployer.undeploy(SCRIPT_DEPLOYMENT_NAME);
|
||||
reconnectAdminClient();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScriptMapperNotAvailableThroughAdminRest() {
|
||||
assertFalse(adminClient.serverInfo().getInfo().getProtocolMapperTypes().get(SamlProtocol.LOGIN_PROTOCOL).stream()
|
||||
.anyMatch(
|
||||
mapper -> ScriptBasedMapper.PROVIDER_ID.equals(mapper.getId())));
|
||||
|
||||
// Doublecheck not possible to create mapper through admin REST
|
||||
ProtocolMapperRepresentation mapperRep = createSamlProtocolMapper(ScriptBasedMapper.PROVIDER_ID,
|
||||
ProviderConfigProperty.SCRIPT_TYPE, "'hello_' + user.username",
|
||||
AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, AttributeStatementHelper.BASIC,
|
||||
AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "SCRIPT_ATTRIBUTE"
|
||||
);
|
||||
|
||||
Response response = pmu.getResource().createMapper(mapperRep);
|
||||
Assert.assertEquals(404, response.getStatus());
|
||||
response.close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@EnableFeature(value = SCRIPTS, skipRestart = true, executeAsLast = false)
|
||||
public void testScriptMappingThroughServerDeploy() {
|
||||
// ScriptBasedMapper still not available even if SCRIPTS feature is enabled
|
||||
testScriptMapperNotAvailableThroughAdminRest();
|
||||
|
||||
pmu.add(
|
||||
createSamlProtocolMapper("script-mapper-a.js",
|
||||
AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, AttributeStatementHelper.BASIC,
|
||||
AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "SCRIPT_ATTRIBUTE"
|
||||
)
|
||||
).update();
|
||||
|
||||
assertLoginSuccessWithAttributeAvailable();
|
||||
}
|
||||
|
||||
|
||||
private void assertLoginSuccessWithAttributeAvailable() {
|
||||
SAMLDocumentHolder samlResponse = new SamlClientBuilder()
|
||||
.authnRequest(getAuthServerSamlEndpoint(REALM_NAME), SAML_CLIENT_ID_EMPLOYEE_2, RoleMapperTest.SAML_ASSERTION_CONSUMER_URL_EMPLOYEE_2, SamlClient.Binding.POST)
|
||||
.build()
|
||||
.login().user(bburkeUser).build()
|
||||
.getSamlResponse(SamlClient.Binding.POST);
|
||||
|
||||
assertThat(samlResponse.getSamlObject(), Matchers.isSamlResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
|
||||
|
||||
Stream<AssertionType> assertions = assertionsUnencrypted(samlResponse.getSamlObject());
|
||||
Stream<AttributeType> attributes = attributesUnecrypted(attributeStatements(assertions));
|
||||
String scriptAttrValue = attributes
|
||||
.filter(attribute -> "SCRIPT_ATTRIBUTE".equals(attribute.getName()))
|
||||
.map(attribute -> attribute.getAttributeValue().get(0).toString())
|
||||
.findFirst().orElseThrow(() -> new AssertionError("Attribute SCRIPT_ATTRIBUTE was not available in SAML assertion"));
|
||||
|
||||
Assert.assertEquals("hello_bburke", scriptAttrValue);
|
||||
}
|
||||
|
||||
}
|
|
@ -40,6 +40,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.platform.Platform;
|
||||
import org.keycloak.protocol.ProtocolMapperSpi;
|
||||
import org.keycloak.protocol.oidc.mappers.DeployedScriptOIDCProtocolMapper;
|
||||
import org.keycloak.protocol.saml.mappers.DeployedScriptSAMLProtocolMapper;
|
||||
import org.keycloak.provider.KeycloakDeploymentInfo;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.ProviderManager;
|
||||
|
@ -601,6 +602,9 @@ public class KeycloakServer {
|
|||
addScriptProvider(info, scriptProviderDescriptor.getProviders().getOrDefault("mappers", Collections.emptyList()),
|
||||
ProtocolMapperSpi.class,
|
||||
DeployedScriptOIDCProtocolMapper::new);
|
||||
addScriptProvider(info, scriptProviderDescriptor.getProviders().getOrDefault("saml-mappers", Collections.emptyList()),
|
||||
ProtocolMapperSpi.class,
|
||||
DeployedScriptSAMLProtocolMapper::new);
|
||||
addScriptProvider(info, scriptProviderDescriptor.getProviders().getOrDefault("policies", Collections.emptyList()),
|
||||
PolicySpi.class,
|
||||
DeployedScriptPolicyFactory::new);
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.subsystem.server.extension;
|
|||
import static org.keycloak.representations.provider.ScriptProviderDescriptor.AUTHENTICATORS;
|
||||
import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAPPERS;
|
||||
import static org.keycloak.representations.provider.ScriptProviderDescriptor.POLICIES;
|
||||
import static org.keycloak.representations.provider.ScriptProviderDescriptor.SAML_MAPPERS;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -39,6 +40,7 @@ import org.keycloak.authorization.policy.provider.js.DeployedScriptPolicyFactory
|
|||
import org.keycloak.common.util.StreamUtil;
|
||||
import org.keycloak.protocol.ProtocolMapperSpi;
|
||||
import org.keycloak.protocol.oidc.mappers.DeployedScriptOIDCProtocolMapper;
|
||||
import org.keycloak.protocol.saml.mappers.DeployedScriptSAMLProtocolMapper;
|
||||
import org.keycloak.provider.KeycloakDeploymentInfo;
|
||||
import org.keycloak.representations.provider.ScriptProviderDescriptor;
|
||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||
|
@ -63,6 +65,10 @@ final class ScriptProviderDeploymentProcessor {
|
|||
info.addProvider(ProtocolMapperSpi.class, new DeployedScriptOIDCProtocolMapper(metadata));
|
||||
}
|
||||
|
||||
private static void registerSAMLScriptMapper(KeycloakDeploymentInfo info, ScriptProviderMetadata metadata) {
|
||||
info.addProvider(ProtocolMapperSpi.class, new DeployedScriptSAMLProtocolMapper(metadata));
|
||||
}
|
||||
|
||||
static void deploy(DeploymentUnit deploymentUnit, KeycloakDeploymentInfo info) {
|
||||
ResourceRoot resourceRoot = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);
|
||||
|
||||
|
@ -129,5 +135,6 @@ final class ScriptProviderDeploymentProcessor {
|
|||
PROVIDERS.put(AUTHENTICATORS, ScriptProviderDeploymentProcessor::registerScriptAuthenticator);
|
||||
PROVIDERS.put(POLICIES, ScriptProviderDeploymentProcessor::registerScriptPolicy);
|
||||
PROVIDERS.put(MAPPERS, ScriptProviderDeploymentProcessor::registerScriptMapper);
|
||||
PROVIDERS.put(SAML_MAPPERS, ScriptProviderDeploymentProcessor::registerSAMLScriptMapper);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue