[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 {
|
public final class DeployedScriptPolicyFactory extends JSPolicyProviderFactory {
|
||||||
|
|
||||||
private final ScriptProviderMetadata metadata;
|
private ScriptProviderMetadata metadata;
|
||||||
|
|
||||||
public DeployedScriptPolicyFactory(ScriptProviderMetadata metadata) {
|
public DeployedScriptPolicyFactory(ScriptProviderMetadata metadata) {
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeployedScriptPolicyFactory() {
|
||||||
|
// for reflection
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return metadata.getId();
|
return metadata.getId();
|
||||||
|
@ -81,4 +85,12 @@ public final class DeployedScriptPolicyFactory extends JSPolicyProviderFactory {
|
||||||
policy.setDescription(metadata.getDescription());
|
policy.setDescription(metadata.getDescription());
|
||||||
super.onCreate(policy, representation, authorization);
|
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;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCode() {
|
public String getCode() {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,21 @@ package org.keycloak.quarkus.deployment;
|
||||||
|
|
||||||
import static org.keycloak.configuration.Configuration.getPropertyNames;
|
import static org.keycloak.configuration.Configuration.getPropertyNames;
|
||||||
import static org.keycloak.configuration.Configuration.getRawValue;
|
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 javax.persistence.spi.PersistenceUnitTransactionType;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
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.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -32,6 +41,9 @@ import java.util.NoSuchElementException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ServiceLoader;
|
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.IsDevelopment;
|
||||||
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
|
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.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||||
import org.keycloak.Config;
|
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.Profile;
|
||||||
|
import org.keycloak.common.util.StreamUtil;
|
||||||
import org.keycloak.config.ConfigProviderFactory;
|
import org.keycloak.config.ConfigProviderFactory;
|
||||||
import org.keycloak.configuration.Configuration;
|
import org.keycloak.configuration.Configuration;
|
||||||
import org.keycloak.configuration.KeycloakConfigSourceProvider;
|
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.DefaultJpaConnectionProviderFactory;
|
||||||
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProviderFactory;
|
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProviderFactory;
|
||||||
import org.keycloak.connections.jpa.updater.liquibase.conn.DefaultLiquibaseConnectionProvider;
|
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.EnvironmentDependentProviderFactory;
|
||||||
import org.keycloak.provider.KeycloakDeploymentInfo;
|
import org.keycloak.provider.KeycloakDeploymentInfo;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
@ -70,18 +89,42 @@ import io.quarkus.deployment.annotations.Record;
|
||||||
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||||
import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem;
|
import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem;
|
||||||
import io.quarkus.vertx.http.deployment.FilterBuildItem;
|
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.NotFoundHandler;
|
||||||
import org.keycloak.services.ServicesLogger;
|
import org.keycloak.services.ServicesLogger;
|
||||||
import org.keycloak.services.health.KeycloakMetricsHandler;
|
import org.keycloak.services.health.KeycloakMetricsHandler;
|
||||||
import org.keycloak.services.resources.KeycloakApplication;
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
import org.keycloak.transaction.JBossJtaTransactionManagerLookup;
|
import org.keycloak.transaction.JBossJtaTransactionManagerLookup;
|
||||||
import org.keycloak.util.Environment;
|
import org.keycloak.util.Environment;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
class KeycloakProcessor {
|
class KeycloakProcessor {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(KeycloakProcessor.class);
|
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 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
|
@BuildStep
|
||||||
FeatureBuildItem getFeature() {
|
FeatureBuildItem getFeature() {
|
||||||
|
@ -125,8 +168,9 @@ class KeycloakProcessor {
|
||||||
Profile.setInstance(recorder.createProfile());
|
Profile.setInstance(recorder.createProfile());
|
||||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories = new HashMap<>();
|
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories = new HashMap<>();
|
||||||
Map<Class<? extends Provider>, String> defaultProviders = 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()) {
|
.entrySet()) {
|
||||||
checkProviders(entry.getKey(), entry.getValue(), defaultProviders);
|
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"));
|
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();
|
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<>();
|
Map<Spi, Map<Class<? extends Provider>, Map<String, ProviderFactory>>> factories = new HashMap<>();
|
||||||
|
|
||||||
for (Spi spi : pm.loadSpis()) {
|
for (Spi spi : pm.loadSpis()) {
|
||||||
Map<Class<? extends Provider>, Map<String, ProviderFactory>> providers = new HashMap<>();
|
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(
|
if (Arrays.asList(
|
||||||
JBossJtaTransactionManagerLookup.class,
|
JBossJtaTransactionManagerLookup.class,
|
||||||
DefaultJpaConnectionProviderFactory.class,
|
DefaultJpaConnectionProviderFactory.class,
|
||||||
|
@ -282,6 +333,86 @@ class KeycloakProcessor {
|
||||||
return factories;
|
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) {
|
private boolean isEnabled(ProviderFactory factory, Config.Scope scope) {
|
||||||
if (!scope.getBoolean("enabled", true)) {
|
if (!scope.getBoolean("enabled", true)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -31,13 +31,16 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
|
||||||
private static QuarkusKeycloakSessionFactory INSTANCE;
|
private static QuarkusKeycloakSessionFactory INSTANCE;
|
||||||
private final Boolean reaugmented;
|
private final Boolean reaugmented;
|
||||||
private final Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories;
|
private final Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories;
|
||||||
|
private Map<String, ProviderFactory> preConfiguredProviders;
|
||||||
|
|
||||||
public QuarkusKeycloakSessionFactory(
|
public QuarkusKeycloakSessionFactory(
|
||||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
|
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
|
||||||
Map<Class<? extends Provider>, String> defaultProviders,
|
Map<Class<? extends Provider>, String> defaultProviders,
|
||||||
|
Map<String, ProviderFactory> preConfiguredProviders,
|
||||||
Boolean reaugmented) {
|
Boolean reaugmented) {
|
||||||
this.provider = defaultProviders;
|
this.provider = defaultProviders;
|
||||||
this.factories = factories;
|
this.factories = factories;
|
||||||
|
this.preConfiguredProviders = preConfiguredProviders;
|
||||||
this.reaugmented = reaugmented;
|
this.reaugmented = reaugmented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +57,12 @@ public final class QuarkusKeycloakSessionFactory extends DefaultKeycloakSessionF
|
||||||
for (Spi spi : spis) {
|
for (Spi spi : spis) {
|
||||||
for (Map<String, Class<? extends ProviderFactory>> factoryClazz : factories.get(spi).values()) {
|
for (Map<String, Class<? extends ProviderFactory>> factoryClazz : factories.get(spi).values()) {
|
||||||
for (Map.Entry<String, Class<? extends ProviderFactory>> entry : factoryClazz.entrySet()) {
|
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());
|
Config.Scope scope = Config.scope(spi.getName(), factory.getId());
|
||||||
|
|
||||||
factory.init(scope);
|
factory.init(scope);
|
||||||
|
|
|
@ -77,9 +77,10 @@ public class KeycloakRecorder {
|
||||||
public void configSessionFactory(
|
public void configSessionFactory(
|
||||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
|
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories,
|
||||||
Map<Class<? extends Provider>, String> defaultProviders,
|
Map<Class<? extends Provider>, String> defaultProviders,
|
||||||
|
Map<String, ProviderFactory> preConfiguredProviders,
|
||||||
Boolean reaugmented) {
|
Boolean reaugmented) {
|
||||||
Profile.setInstance(createProfile());
|
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;
|
package org.keycloak.authentication.authenticators.browser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.Authenticator;
|
import org.keycloak.authentication.Authenticator;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.models.AuthenticatorConfigModel;
|
import org.keycloak.models.AuthenticatorConfigModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,17 +34,16 @@ import org.keycloak.representations.provider.ScriptProviderMetadata;
|
||||||
*/
|
*/
|
||||||
public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthenticatorFactory {
|
public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthenticatorFactory {
|
||||||
|
|
||||||
private final AuthenticatorConfigModel model;
|
private ScriptProviderMetadata metadata;
|
||||||
|
private AuthenticatorConfigModel model;
|
||||||
|
private List<ProviderConfigProperty> configProperties;
|
||||||
|
|
||||||
public DeployedScriptAuthenticatorFactory(ScriptProviderMetadata metadata) {
|
public DeployedScriptAuthenticatorFactory(ScriptProviderMetadata metadata) {
|
||||||
model = new AuthenticatorConfigModel();
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
model.setId(metadata.getId());
|
public DeployedScriptAuthenticatorFactory() {
|
||||||
model.setAlias(metadata.getName());
|
// for reflection
|
||||||
model.setConfig(new HashMap<>());
|
|
||||||
model.getConfig().put("scriptName", metadata.getName());
|
|
||||||
model.getConfig().put("scriptCode", metadata.getCode());
|
|
||||||
model.getConfig().put("scriptDescription", metadata.getDescription());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,7 +58,7 @@ public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthent
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return model.getId();
|
return metadata.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,4 +85,36 @@ public final class DeployedScriptAuthenticatorFactory extends ScriptBasedAuthent
|
||||||
public boolean isSupported() {
|
public boolean isSupported() {
|
||||||
return Profile.isFeatureEnabled(Profile.Feature.SCRIPTS);
|
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 java.util.List;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
|
@ -25,30 +26,20 @@ import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.provider.ProviderConfigurationBuilder;
|
import org.keycloak.provider.ProviderConfigurationBuilder;
|
||||||
import org.keycloak.representations.provider.ScriptProviderMetadata;
|
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 {
|
protected ScriptProviderMetadata metadata;
|
||||||
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;
|
|
||||||
|
|
||||||
public DeployedScriptOIDCProtocolMapper(ScriptProviderMetadata metadata) {
|
public DeployedScriptOIDCProtocolMapper(ScriptProviderMetadata metadata) {
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeployedScriptOIDCProtocolMapper() {
|
||||||
|
// for reflection
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return metadata.getId();
|
return metadata.getId();
|
||||||
|
@ -69,6 +60,21 @@ public final class DeployedScriptOIDCProtocolMapper extends ScriptBasedOIDCProto
|
||||||
return metadata.getCode();
|
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() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
@ -77,4 +83,12 @@ public final class DeployedScriptOIDCProtocolMapper extends ScriptBasedOIDCProto
|
||||||
public boolean isSupported() {
|
public boolean isSupported() {
|
||||||
return Profile.isFeatureEnabled(Profile.Feature.SCRIPTS);
|
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