[KEYCLOAK-17173] - Support for script providers in keycloak.x
This commit is contained in:
parent
1dc0b005fe
commit
ffadbc3ba3
7 changed files with 243 additions and 34 deletions
|
@ -30,12 +30,16 @@ import org.keycloak.scripting.ScriptingProvider;
|
|||
*/
|
||||
public final class DeployedScriptPolicyFactory extends JSPolicyProviderFactory {
|
||||
|
||||
private final ScriptProviderMetadata metadata;
|
||||
private ScriptProviderMetadata metadata;
|
||||
|
||||
public DeployedScriptPolicyFactory(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public DeployedScriptPolicyFactory() {
|
||||
// for reflection
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return metadata.getId();
|
||||
|
@ -81,4 +85,12 @@ public final class DeployedScriptPolicyFactory extends JSPolicyProviderFactory {
|
|||
policy.setDescription(metadata.getDescription());
|
||||
super.onCreate(policy, representation, authorization);
|
||||
}
|
||||
|
||||
public ScriptProviderMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,10 +59,18 @@ public class ScriptProviderMetadata {
|
|||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,21 @@ package org.keycloak.quarkus.deployment;
|
|||
|
||||
import static org.keycloak.configuration.Configuration.getPropertyNames;
|
||||
import static org.keycloak.configuration.Configuration.getRawValue;
|
||||
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 javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -32,6 +41,9 @@ import java.util.NoSuchElementException;
|
|||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import io.quarkus.deployment.IsDevelopment;
|
||||
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
|
||||
|
@ -46,7 +58,12 @@ import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.AuthenticatorSpi;
|
||||
import org.keycloak.authentication.authenticators.browser.DeployedScriptAuthenticatorFactory;
|
||||
import org.keycloak.authorization.policy.provider.PolicySpi;
|
||||
import org.keycloak.authorization.policy.provider.js.DeployedScriptPolicyFactory;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.StreamUtil;
|
||||
import org.keycloak.config.ConfigProviderFactory;
|
||||
import org.keycloak.configuration.Configuration;
|
||||
import org.keycloak.configuration.KeycloakConfigSourceProvider;
|
||||
|
@ -54,6 +71,8 @@ import org.keycloak.configuration.MicroProfileConfigProvider;
|
|||
import org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory;
|
||||
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProviderFactory;
|
||||
import org.keycloak.connections.jpa.updater.liquibase.conn.DefaultLiquibaseConnectionProvider;
|
||||
import org.keycloak.protocol.ProtocolMapperSpi;
|
||||
import org.keycloak.protocol.oidc.mappers.DeployedScriptOIDCProtocolMapper;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.KeycloakDeploymentInfo;
|
||||
import org.keycloak.provider.Provider;
|
||||
|
@ -70,18 +89,42 @@ import io.quarkus.deployment.annotations.Record;
|
|||
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||
import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem;
|
||||
import io.quarkus.vertx.http.deployment.FilterBuildItem;
|
||||
import org.keycloak.representations.provider.ScriptProviderDescriptor;
|
||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||
import org.keycloak.services.NotFoundHandler;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.health.KeycloakMetricsHandler;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
import org.keycloak.transaction.JBossJtaTransactionManagerLookup;
|
||||
import org.keycloak.util.Environment;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
class KeycloakProcessor {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(KeycloakProcessor.class);
|
||||
|
||||
private static final String JAR_FILE_SEPARATOR = "!/";
|
||||
private static final String DEFAULT_HEALTH_ENDPOINT = "/health";
|
||||
private static final Map<String, Function<ScriptProviderMetadata, ProviderFactory>> DEPLOYEABLE_SCRIPT_PROVIDERS = new HashMap<>();
|
||||
private static final String KEYCLOAK_SCRIPTS_JSON_PATH = "META-INF/keycloak-scripts.json";
|
||||
|
||||
static {
|
||||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(AUTHENTICATORS, KeycloakProcessor::registerScriptAuthenticator);
|
||||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(POLICIES, KeycloakProcessor::registerScriptPolicy);
|
||||
DEPLOYEABLE_SCRIPT_PROVIDERS.put(MAPPERS, KeycloakProcessor::registerScriptMapper);
|
||||
}
|
||||
|
||||
private static ProviderFactory registerScriptAuthenticator(ScriptProviderMetadata metadata) {
|
||||
return new DeployedScriptAuthenticatorFactory(metadata);
|
||||
}
|
||||
|
||||
private static ProviderFactory registerScriptPolicy(ScriptProviderMetadata metadata) {
|
||||
return new DeployedScriptPolicyFactory(metadata);
|
||||
}
|
||||
|
||||
private static ProviderFactory registerScriptMapper(ScriptProviderMetadata metadata) {
|
||||
return new DeployedScriptOIDCProtocolMapper(metadata);
|
||||
}
|
||||
|
||||
@BuildStep
|
||||
FeatureBuildItem getFeature() {
|
||||
|
@ -125,8 +168,9 @@ class KeycloakProcessor {
|
|||
Profile.setInstance(recorder.createProfile());
|
||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories = new HashMap<>();
|
||||
Map<Class<? extends Provider>, String> defaultProviders = new HashMap<>();
|
||||
Map<String, ProviderFactory> preConfiguredProviders = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Spi, Map<Class<? extends Provider>, Map<String, ProviderFactory>>> entry : loadFactories()
|
||||
for (Map.Entry<Spi, Map<Class<? extends Provider>, Map<String, ProviderFactory>>> entry : loadFactories(preConfiguredProviders)
|
||||
.entrySet()) {
|
||||
checkProviders(entry.getKey(), entry.getValue(), defaultProviders);
|
||||
|
||||
|
@ -139,7 +183,7 @@ class KeycloakProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
recorder.configSessionFactory(factories, defaultProviders, Environment.isRebuild());
|
||||
recorder.configSessionFactory(factories, defaultProviders, preConfiguredProviders, Environment.isRebuild());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,15 +289,22 @@ class KeycloakProcessor {
|
|||
hotFiles.produce(new HotDeploymentWatchedFileBuildItem("META-INF/keycloak.properties"));
|
||||
}
|
||||
|
||||
private Map<Spi, Map<Class<? extends Provider>, Map<String, ProviderFactory>>> loadFactories() {
|
||||
private Map<Spi, Map<Class<? extends Provider>, Map<String, ProviderFactory>>> loadFactories(
|
||||
Map<String, ProviderFactory> preConfiguredProviders) {
|
||||
loadConfig();
|
||||
ProviderManager pm = new ProviderManager(KeycloakDeploymentInfo.create().services(), new BuildClassLoader());
|
||||
BuildClassLoader providerClassLoader = new BuildClassLoader();
|
||||
ProviderManager pm = new ProviderManager(KeycloakDeploymentInfo.create().services(), providerClassLoader);
|
||||
Map<Spi, Map<Class<? extends Provider>, Map<String, ProviderFactory>>> factories = new HashMap<>();
|
||||
|
||||
for (Spi spi : pm.loadSpis()) {
|
||||
Map<Class<? extends Provider>, Map<String, ProviderFactory>> providers = new HashMap<>();
|
||||
List<ProviderFactory> loadedFactories = new ArrayList<>(pm.load(spi));
|
||||
Map<String, ProviderFactory> deployedScriptProviders = loadDeployedScriptProviders(providerClassLoader, spi);
|
||||
|
||||
for (ProviderFactory factory : pm.load(spi)) {
|
||||
loadedFactories.addAll(deployedScriptProviders.values());
|
||||
preConfiguredProviders.putAll(deployedScriptProviders);
|
||||
|
||||
for (ProviderFactory factory : loadedFactories) {
|
||||
if (Arrays.asList(
|
||||
JBossJtaTransactionManagerLookup.class,
|
||||
DefaultJpaConnectionProviderFactory.class,
|
||||
|
@ -282,6 +333,86 @@ class KeycloakProcessor {
|
|||
return factories;
|
||||
}
|
||||
|
||||
private Map<String, ProviderFactory> loadDeployedScriptProviders(BuildClassLoader providerClassLoader, Spi spi) {
|
||||
Map<String, ProviderFactory> providers = new HashMap<>();
|
||||
|
||||
if (supportsDeployeableScripts(spi)) {
|
||||
try {
|
||||
Enumeration<URL> urls = providerClassLoader.getResources(KEYCLOAK_SCRIPTS_JSON_PATH);
|
||||
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = urls.nextElement();
|
||||
int fileSeparator = url.getFile().indexOf(JAR_FILE_SEPARATOR);
|
||||
|
||||
if (fileSeparator != -1) {
|
||||
JarFile jarFile = new JarFile(url.getFile().substring("file:".length(), fileSeparator));
|
||||
JarEntry descriptorEntry = jarFile.getJarEntry(KEYCLOAK_SCRIPTS_JSON_PATH);
|
||||
ScriptProviderDescriptor descriptor;
|
||||
|
||||
try (InputStream is = jarFile.getInputStream(descriptorEntry)) {
|
||||
descriptor = JsonSerialization.readValue(is, ScriptProviderDescriptor.class);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<ScriptProviderMetadata>> entry : descriptor.getProviders().entrySet()) {
|
||||
if (isScriptForSpi(spi, entry.getKey())) {
|
||||
for (ScriptProviderMetadata metadata : entry.getValue()) {
|
||||
ProviderFactory provider = createDeployableScriptProvider(jarFile, entry, metadata);
|
||||
providers.put(metadata.getId(), provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to discover script providers", e);
|
||||
}
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
private ProviderFactory createDeployableScriptProvider(JarFile jarFile, Map.Entry<String, List<ScriptProviderMetadata>> entry,
|
||||
ScriptProviderMetadata metadata) throws IOException {
|
||||
String fileName = metadata.getFileName();
|
||||
|
||||
if (fileName == null) {
|
||||
throw new RuntimeException("You must provide the script file name");
|
||||
}
|
||||
|
||||
JarEntry scriptFile = jarFile.getJarEntry(fileName);
|
||||
|
||||
try (InputStream in = jarFile.getInputStream(scriptFile)) {
|
||||
metadata.setCode(StreamUtil.readString(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
metadata.setId(new StringBuilder("script").append("-").append(fileName).toString());
|
||||
|
||||
String name = metadata.getName();
|
||||
|
||||
if (name == null) {
|
||||
name = fileName;
|
||||
}
|
||||
|
||||
metadata.setName(name);
|
||||
|
||||
return DEPLOYEABLE_SCRIPT_PROVIDERS.get(entry.getKey()).apply(metadata);
|
||||
}
|
||||
|
||||
private boolean isScriptForSpi(Spi spi, String type) {
|
||||
if (spi instanceof ProtocolMapperSpi && MAPPERS.equals(type)) {
|
||||
return true;
|
||||
} else if (spi instanceof PolicySpi && POLICIES.equals(type)) {
|
||||
return true;
|
||||
} else if (spi instanceof AuthenticatorSpi && AUTHENTICATORS.equals(type)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean supportsDeployeableScripts(Spi spi) {
|
||||
return spi instanceof ProtocolMapperSpi || spi instanceof PolicySpi || spi instanceof AuthenticatorSpi;
|
||||
}
|
||||
|
||||
private boolean isEnabled(ProviderFactory factory, Config.Scope scope) {
|
||||
if (!scope.getBoolean("enabled", true)) {
|
||||
return false;
|
||||
|
|
|
@ -31,13 +31,16 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
|
|||
private static QuarkusKeycloakSessionFactory INSTANCE;
|
||||
private final Boolean reaugmented;
|
||||
private final Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories;
|
||||
private Map<String, ProviderFactory> preConfiguredProviders;
|
||||
|
||||
public QuarkusKeycloakSessionFactory(
|
||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
|
||||
Map<Class<? extends Provider>, String> defaultProviders,
|
||||
Map<String, ProviderFactory> preConfiguredProviders,
|
||||
Boolean reaugmented) {
|
||||
this.provider = defaultProviders;
|
||||
this.factories = factories;
|
||||
this.preConfiguredProviders = preConfiguredProviders;
|
||||
this.reaugmented = reaugmented;
|
||||
}
|
||||
|
||||
|
@ -54,7 +57,12 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
|
|||
for (Spi spi : spis) {
|
||||
for (Map<String, Class<? extends ProviderFactory>> factoryClazz : factories.get(spi).values()) {
|
||||
for (Map.Entry<String, Class<? extends ProviderFactory>> entry : factoryClazz.entrySet()) {
|
||||
ProviderFactory factory = lookupProviderFactory(entry.getValue());
|
||||
ProviderFactory factory = preConfiguredProviders.get(entry.getKey());
|
||||
|
||||
if (factory == null) {
|
||||
factory = lookupProviderFactory(entry.getValue());
|
||||
}
|
||||
|
||||
Config.Scope scope = Config.scope(spi.getName(), factory.getId());
|
||||
|
||||
factory.init(scope);
|
||||
|
|
|
@ -77,9 +77,10 @@ public class KeycloakRecorder {
|
|||
public void configSessionFactory(
|
||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
|
||||
Map<Class<? extends Provider>, String> defaultProviders,
|
||||
Map<String, ProviderFactory> preConfiguredProviders,
|
||||
Boolean reaugmented) {
|
||||
Profile.setInstance(createProfile());
|
||||
QuarkusKeycloakSessionFactory.setInstance(new QuarkusKeycloakSessionFactory(factories, defaultProviders, reaugmented));
|
||||
QuarkusKeycloakSessionFactory.setInstance(new QuarkusKeycloakSessionFactory(factories, defaultProviders, preConfiguredProviders, reaugmented));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,13 +16,17 @@
|
|||
*/
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||
|
||||
/**
|
||||
|
@ -30,17 +34,16 @@ import org.keycloak.representations.provider.ScriptProviderMetadata;
|
|||
*/
|
||||
public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthenticatorFactory {
|
||||
|
||||
private final AuthenticatorConfigModel model;
|
||||
private ScriptProviderMetadata metadata;
|
||||
private AuthenticatorConfigModel model;
|
||||
private List<ProviderConfigProperty> configProperties;
|
||||
|
||||
public DeployedScriptAuthenticatorFactory(ScriptProviderMetadata metadata) {
|
||||
model = new AuthenticatorConfigModel();
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
model.setId(metadata.getId());
|
||||
model.setAlias(metadata.getName());
|
||||
model.setConfig(new HashMap<>());
|
||||
model.getConfig().put("scriptName", metadata.getName());
|
||||
model.getConfig().put("scriptCode", metadata.getCode());
|
||||
model.getConfig().put("scriptDescription", metadata.getDescription());
|
||||
public DeployedScriptAuthenticatorFactory() {
|
||||
// for reflection
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,7 +58,7 @@ public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthent
|
|||
|
||||
@Override
|
||||
public String getId() {
|
||||
return model.getId();
|
||||
return metadata.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,4 +85,36 @@ public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthent
|
|||
public boolean isSupported() {
|
||||
return Profile.isFeatureEnabled(Profile.Feature.SCRIPTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
model = createModel(metadata);
|
||||
configProperties = super.getConfigProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
}
|
||||
|
||||
public void setMetadata(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public ScriptProviderMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private AuthenticatorConfigModel createModel(ScriptProviderMetadata metadata) {
|
||||
AuthenticatorConfigModel model = new AuthenticatorConfigModel();
|
||||
|
||||
model.setId(metadata.getId());
|
||||
model.setAlias(metadata.getName());
|
||||
model.setConfig(new HashMap<>());
|
||||
model.getConfig().put("scriptName", metadata.getName());
|
||||
model.getConfig().put("scriptCode", metadata.getCode());
|
||||
model.getConfig().put("scriptDescription", metadata.getDescription());
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.keycloak.protocol.oidc.mappers;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
|
@ -25,30 +26,20 @@ import org.keycloak.provider.ProviderConfigProperty;
|
|||
import org.keycloak.provider.ProviderConfigurationBuilder;
|
||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||
|
||||
public final class DeployedScriptOIDCProtocolMapper extends ScriptBasedOIDCProtocolMapper {
|
||||
public class DeployedScriptOIDCProtocolMapper extends ScriptBasedOIDCProtocolMapper {
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties;
|
||||
private List<ProviderConfigProperty> configProperties;
|
||||
|
||||
static {
|
||||
configProperties = ProviderConfigurationBuilder.create()
|
||||
.property()
|
||||
.name(ProtocolMapperUtils.MULTIVALUED)
|
||||
.label(ProtocolMapperUtils.MULTIVALUED_LABEL)
|
||||
.helpText(ProtocolMapperUtils.MULTIVALUED_HELP_TEXT)
|
||||
.type(ProviderConfigProperty.BOOLEAN_TYPE)
|
||||
.defaultValue(false)
|
||||
.add()
|
||||
.build();
|
||||
|
||||
OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserPropertyMapper.class);
|
||||
}
|
||||
|
||||
private final ScriptProviderMetadata metadata;
|
||||
protected ScriptProviderMetadata metadata;
|
||||
|
||||
public DeployedScriptOIDCProtocolMapper(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public DeployedScriptOIDCProtocolMapper() {
|
||||
// for reflection
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return metadata.getId();
|
||||
|
@ -69,6 +60,21 @@ public final class DeployedScriptOIDCProtocolMapper extends ScriptBasedOIDCProto
|
|||
return metadata.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
configProperties = ProviderConfigurationBuilder.create()
|
||||
.property()
|
||||
.name(ProtocolMapperUtils.MULTIVALUED)
|
||||
.label(ProtocolMapperUtils.MULTIVALUED_LABEL)
|
||||
.helpText(ProtocolMapperUtils.MULTIVALUED_HELP_TEXT)
|
||||
.type(ProviderConfigProperty.BOOLEAN_TYPE)
|
||||
.defaultValue(false)
|
||||
.add()
|
||||
.build();
|
||||
|
||||
OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserPropertyMapper.class);
|
||||
}
|
||||
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
}
|
||||
|
@ -77,4 +83,12 @@ public final class DeployedScriptOIDCProtocolMapper extends ScriptBasedOIDCProto
|
|||
public boolean isSupported() {
|
||||
return Profile.isFeatureEnabled(Profile.Feature.SCRIPTS);
|
||||
}
|
||||
|
||||
public void setMetadata(ScriptProviderMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public ScriptProviderMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue