diff --git a/.gitignore b/.gitignore index 336b753a9..835791c49 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ release.properties /*.json /test* +/exports diff --git a/docs/FEATURES.md b/docs/FEATURES.md index ab05ea621..429b354bb 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -57,6 +57,7 @@ | Synchronize user profile | 5.4.0 | Synchronize the user profile configuration defined on the realm configuration | | Synchronize client-policies | 5.6.0 | Synchronize the client-policies (clientProfiles and clientPolicies) while updating realms | | Synchronize message bundles | 5.12.0 | Synchronize message bundles defined on the realm configuration | +| Normalize realm exports | x.x.x | Normalize a full realm export to be more minimal | # Specificities diff --git a/docs/NORMALIZE.md b/docs/NORMALIZE.md new file mode 100644 index 000000000..0df106179 --- /dev/null +++ b/docs/NORMALIZE.md @@ -0,0 +1,123 @@ +# Realm normalization + +Realm normalization is a feature that is supposed to aid users in migrating from an "unmanaged" Keycloak installation, +to an installation managed by keycloak-config-cli. +To achieve this, it uses a full [realm export](https://www.keycloak.org/server/importExport#_exporting_a_specific_realm) +as an input, and only retains things that deviate from the default + +## Usage + +To run the normalization, run keycloak-config-cli with the CLI option `--run.operation=NORMALIZE`. +The default value for this option is `IMPORT`, which will run the regular keycloak-config-cli import. + +### Configuration options + +| Configuration key | Purpose | Example | +|--------------------------------------|-----------------------------------------------------------------------------------------------------------------|---------------| +| run.operation | Tell keycloak-config-cli to normalize, rather than import | NORMALIZE | +| normalization.files.input-locations | Which realm files to import | See IMPORT.md | +| normalization.files.output-directory | Where to save output realm files | ./exports/out | +| normalization.output-format | Whether to output JSON or YAML. Default value is YAML | YAML | +| normalization.fallback-version | Use this version as a baseline of keycloak version in realm is not available as baseline in keycloak-config-cli | 19.0.3 | + +### Unimplemented Features +- Components: + - Currently, keycloak-config-cli will not yet look at the `components` section of the exported JSON + - Therefore, some things (like LDAP federation configs and Key providers) are missing from the normalized YAML +- Users + - Users are not currently considered by normalization. + +## Missing entries +keycloak-config-cli will WARN if components that are present in a realm by default are missing from an exported realm. +An example of such a message is: +``` +Default realm requiredAction 'webauthn-register-passwordless' was deleted in exported realm. It may be reintroduced during import +``` +Messages like these will often show up when using keycloak-config-cli to normalize an import from an older version of Keycloak, and compared to a newer baseline. +In the above case, the Keycloak version is 18.0.3, and the baseline for comparison was 19.0.3. +Since the webauthn feature was not present (or enabled by default) in the older version, this message is mostly informative. +If a message like this appears on a component that was *not* deleted or should generally be present, this may indicate a bug in keycloak-config-cli. + +## Cleaning of invalid data +Sometimes, realms of existing installations may contain invalid data, due to faulty migrations, or due to direct interaction with the database, +rather than the Keycloak API. +When such problems are found, we attempt to handle them in keycloak-config-cli, or at least notify the user about the existence of these problems. + +### SAML Attributes on clients +While not necessarily invalid, openid-connect clients that were created on older Keycloak versions, will sometimes contain +SAML-related attributes. These are filtered out by keycloak-config-cli. + +### Unused non-top-level Authentication Flows +Authentication flows in Keycloak are marked as top-level if they are supposed to be available for binding or overrides. +Authentication flows that are not marked as top-level are used as sub-flows in other authentication flows. +The normalization process recognizes recursively whether there are authentication flows that are not top level and not used +by any top level flow, and does not include them in the final result. + +A warning message is logged, and you can use the following SQL query to find any authentication flows that are not referenced. +Note that this query, unlike keycloak-config-cli, is not recursive. +That means that after deleting an unused flow, additional unused flows may appear after the query is performed again. + +```sql +select flow.alias +from authentication_flow flow + join realm r on flow.realm_id = r.id + left join authentication_execution execution on flow.id = execution.auth_flow_id +where r.name = 'mytest' + and execution.id is null + and not flow.top_level +``` + +### Unused and duplicate Authenticator Configs +Authenticator Configs are not useful if they are not referenced by at least one authentication execution. +Therefore, keycloak-config-cli detects unused configurations and does not include them in the resulting output. +Note that the check for unused configs runs *after* the check for unused flows. +That means a config will be detected as unused if it is referenced by an execution that is part of a flow that is unused. + +A warning message is logged on duplicate or unused configs, and you can use the following SQL query to find any configs +that are unused: + +```sql +select ac.alias, ac.id +from authenticator_config ac + left join authentication_execution ae on ac.id = ae.auth_config + left join authentication_flow af on ae.flow_id = af.id + join realm r on ac.realm_id = r.id +where r.name = 'master' and af.alias is null +order by ac.alias +``` + +And the following query to find duplicates: + +```sql +select alias, count(alias), r.name as realm_name +from authenticator_config + join realm r on realm_id = r.id +group by alias, r.name +having count(alias) > 1 +``` + +If the `af.id` and `af.alias` fields are `null`, the config in question is not in use. +Note that configs used by unused flows are not marked as unused in the SQL result, as these need to be deleted first +to become unused. +After the unused flows (and executions) are deleted, the configs will be marked as unused and can also be deleted. + +### Authentication Executions with invalid subflows +Some keycloak exports have invalid authentication executions that reference a subflow, while also setting an authenticator. +This is only a valid configuration if the subflow's type is `form-flow`. +If it is not, then keycloak-config-cli will not import the configuration. +This will be marked by an ERROR severity message in the log output. +You can use this SQL query to find offending entries and remediate the configuration errors before continuing. + +```sql +select parent.alias, + subflow.alias, + execution.alias +from authentication_execution execution + join realm r on execution.realm_id = r.id + join authentication_flow parent on execution.flow_id = parent.id + join authentication_flow subflow on execution.auth_flow_id = subflow.id +where execution.auth_flow_id is not null + and execution.authenticator is not null + and subflow.provider_id <> 'form-flow' + and r.name = 'REALMNAME'; +``` diff --git a/pom.xml b/pom.xml index 8c84fb126..e985c92eb 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,7 @@ 2.1.1 2.4.0 8.0 + 7.6.3 3.2.5 3.1.1 1.5.3 @@ -129,6 +130,30 @@ import pom + + + org.apache.commons + commons-text + ${commons-text.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + net.jodah + failsafe + ${failsafe.version} + + + + org.javers + javers-core + ${javers.version} + @@ -170,12 +195,6 @@ jackson-datatype-jdk8 - - org.yaml - snakeyaml - ${snakeyaml.version} - - org.keycloak keycloak-admin-client @@ -209,6 +228,26 @@ ${failsafe.version} + + com.fasterxml.jackson.core + jackson-databind + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + + + org.javers + javers-core + + + + org.yaml + snakeyaml + + net.logstash.logback diff --git a/src/main/java/de/adorsys/keycloak/config/KeycloakConfigApplication.java b/src/main/java/de/adorsys/keycloak/config/KeycloakConfigApplication.java index 5fa682707..99746d177 100644 --- a/src/main/java/de/adorsys/keycloak/config/KeycloakConfigApplication.java +++ b/src/main/java/de/adorsys/keycloak/config/KeycloakConfigApplication.java @@ -20,14 +20,13 @@ package de.adorsys.keycloak.config; -import de.adorsys.keycloak.config.properties.ImportConfigProperties; -import de.adorsys.keycloak.config.properties.KeycloakConfigProperties; +import de.adorsys.keycloak.config.properties.RunConfigProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication(proxyBeanMethods = false) -@EnableConfigurationProperties({KeycloakConfigProperties.class, ImportConfigProperties.class}) +@EnableConfigurationProperties(RunConfigProperties.class) public class KeycloakConfigApplication { public static void main(String[] args) { // https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-application-exit diff --git a/src/main/java/de/adorsys/keycloak/config/KeycloakConfigNormalizationRunner.java b/src/main/java/de/adorsys/keycloak/config/KeycloakConfigNormalizationRunner.java new file mode 100644 index 000000000..44b410b79 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/KeycloakConfigNormalizationRunner.java @@ -0,0 +1,126 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import de.adorsys.keycloak.config.properties.NormalizationConfigProperties; +import de.adorsys.keycloak.config.properties.NormalizationKeycloakConfigProperties; +import de.adorsys.keycloak.config.provider.KeycloakExportProvider; +import de.adorsys.keycloak.config.service.normalize.RealmNormalizationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.ExitCodeGenerator; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.io.FileOutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static de.adorsys.keycloak.config.properties.NormalizationConfigProperties.OutputFormat.YAML; + +@Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +@EnableConfigurationProperties({NormalizationConfigProperties.class, NormalizationKeycloakConfigProperties.class}) +public class KeycloakConfigNormalizationRunner implements CommandLineRunner, ExitCodeGenerator { + + private static final Logger logger = LoggerFactory.getLogger(KeycloakConfigNormalizationRunner.class); + private static final long START_TIME = System.currentTimeMillis(); + + private final RealmNormalizationService normalizationService; + private final KeycloakExportProvider exportProvider; + private final NormalizationConfigProperties normalizationConfigProperties; + private final YAMLMapper yamlMapper; + private final ObjectMapper objectMapper; + private int exitCode; + + @Autowired + public KeycloakConfigNormalizationRunner(RealmNormalizationService normalizationService, + KeycloakExportProvider exportProvider, + NormalizationConfigProperties normalizationConfigProperties, + YAMLMapper yamlMapper, + ObjectMapper objectMapper) { + this.normalizationService = normalizationService; + this.exportProvider = exportProvider; + this.normalizationConfigProperties = normalizationConfigProperties; + this.yamlMapper = yamlMapper; + this.objectMapper = objectMapper; + } + + @Override + public void run(String... args) throws Exception { + try { + var outputLocation = Paths.get(normalizationConfigProperties.getFiles().getOutputDirectory()); + if (!Files.exists(outputLocation)) { + logger.info("Creating output directory '{}'", outputLocation); + Files.createDirectories(outputLocation); + } + if (!Files.isDirectory(outputLocation)) { + logger.error("Output location '{}' is not a directory. Aborting", outputLocation); + exitCode = 1; + return; + } + + for (var exportLocations : exportProvider.readFromLocations().values()) { + for (var export : exportLocations.entrySet()) { + logger.info("Normalizing file '{}'", export.getKey()); + for (var realm : export.getValue()) { + var normalizedRealm = normalizationService.normalizeRealm(realm); + var suffix = normalizationConfigProperties.getOutputFormat() == YAML ? "yaml" : "json"; + var outputFile = outputLocation.resolve(String.format("%s.%s", normalizedRealm.getRealm(), suffix)); + try (var os = new FileOutputStream(outputFile.toFile())) { + if (normalizationConfigProperties.getOutputFormat() == YAML) { + yamlMapper.writeValue(os, normalizedRealm); + } else { + objectMapper.writeValue(os, normalizedRealm); + } + } + } + } + } + } catch (NullPointerException e) { + throw e; + } catch (Exception e) { + logger.error(e.getMessage()); + + exitCode = 1; + + if (logger.isDebugEnabled()) { + throw e; + } + } finally { + long totalTime = System.currentTimeMillis() - START_TIME; + String formattedTime = new SimpleDateFormat("mm:ss.SSS").format(new Date(totalTime)); + logger.info("keycloak-config-cli running in {}.", formattedTime); + } + } + + @Override + public int getExitCode() { + return exitCode; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/KeycloakConfigRunner.java b/src/main/java/de/adorsys/keycloak/config/KeycloakConfigRunner.java index d254adf54..a8fd41002 100644 --- a/src/main/java/de/adorsys/keycloak/config/KeycloakConfigRunner.java +++ b/src/main/java/de/adorsys/keycloak/config/KeycloakConfigRunner.java @@ -23,6 +23,7 @@ import de.adorsys.keycloak.config.model.KeycloakImport; import de.adorsys.keycloak.config.model.RealmImport; import de.adorsys.keycloak.config.properties.ImportConfigProperties; +import de.adorsys.keycloak.config.properties.KeycloakConfigProperties; import de.adorsys.keycloak.config.provider.KeycloakImportProvider; import de.adorsys.keycloak.config.service.RealmImportService; import org.slf4j.Logger; @@ -30,6 +31,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.ExitCodeGenerator; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; @@ -39,6 +42,13 @@ import java.util.Map; @Component +/* + * Spring only considers actual properties set, not default values of @ConfigurationProperties classes. + * Therefore, we enable matchIfMissing here, so if there is *no* property set, we consider it an import + * for backwards compatibility + */ +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) +@EnableConfigurationProperties({ImportConfigProperties.class, KeycloakConfigProperties.class}) public class KeycloakConfigRunner implements CommandLineRunner, ExitCodeGenerator { private static final Logger logger = LoggerFactory.getLogger(KeycloakConfigRunner.class); private static final long START_TIME = System.currentTimeMillis(); diff --git a/src/main/java/de/adorsys/keycloak/config/configuration/NormalizationConfiguration.java b/src/main/java/de/adorsys/keycloak/config/configuration/NormalizationConfiguration.java new file mode 100644 index 000000000..21a43888a --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/configuration/NormalizationConfiguration.java @@ -0,0 +1,137 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.configuration; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import org.javers.core.Javers; +import org.javers.core.JaversBuilder; +import org.javers.core.diff.ListCompareAlgorithm; +import org.javers.core.metamodel.clazz.EntityDefinition; +import org.javers.core.metamodel.clazz.EntityDefinitionBuilder; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ClientScopeRepresentation; +import org.keycloak.representations.idm.ComponentExportRepresentation; +import org.keycloak.representations.idm.GroupRepresentation; +import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.RequiredActionProviderRepresentation; +import org.keycloak.representations.idm.RoleRepresentation; +import org.keycloak.representations.idm.UserFederationMapperRepresentation; +import org.keycloak.representations.idm.UserFederationProviderRepresentation; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class NormalizationConfiguration { + + @Bean + public Javers javers() { + return commonJavers() + .withListCompareAlgorithm(ListCompareAlgorithm.LEVENSHTEIN_DISTANCE) + .build(); + } + + @Bean + public Javers unOrderedJavers() { + return commonJavers() + .withListCompareAlgorithm(ListCompareAlgorithm.AS_SET) + .build(); + } + + @Bean + public YAMLMapper yamlMapper() { + var ym = new YAMLMapper(); + ym.setSerializationInclusion(JsonInclude.Include.NON_NULL); + ym.enable(SerializationFeature.INDENT_OUTPUT); + ym.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR); + return ym; + } + + @Bean + public ObjectMapper objectMapper() { + var om = new ObjectMapper(); + om.setSerializationInclusion(JsonInclude.Include.NON_NULL); + om.enable(SerializationFeature.INDENT_OUTPUT); + return om; + } + + private JaversBuilder commonJavers() { + var realmIgnoredProperties = new ArrayList(); + realmIgnoredProperties.add("id"); + realmIgnoredProperties.add("groups"); + realmIgnoredProperties.add("roles"); + realmIgnoredProperties.add("defaultRole"); + realmIgnoredProperties.add("clientProfiles"); // + realmIgnoredProperties.add("clientPolicies"); // + realmIgnoredProperties.add("users"); + realmIgnoredProperties.add("federatedUsers"); + realmIgnoredProperties.add("scopeMappings"); // + realmIgnoredProperties.add("clientScopeMappings"); // + realmIgnoredProperties.add("clients"); // + realmIgnoredProperties.add("clientScopes"); // + realmIgnoredProperties.add("userFederationProviders"); + realmIgnoredProperties.add("userFederationMappers"); + realmIgnoredProperties.add("identityProviders"); + realmIgnoredProperties.add("identityProviderMappers"); + realmIgnoredProperties.add("protocolMappers"); // + realmIgnoredProperties.add("components"); + realmIgnoredProperties.add("authenticationFlows"); + realmIgnoredProperties.add("authenticatorConfig"); + realmIgnoredProperties.add("requiredActions"); + realmIgnoredProperties.add("applicationScopeMappings"); + realmIgnoredProperties.add("applications"); + realmIgnoredProperties.add("oauthClients"); + realmIgnoredProperties.add("clientTemplates"); + realmIgnoredProperties.add("attributes"); + + return JaversBuilder.javers() + .registerEntity(new EntityDefinition(RealmRepresentation.class, "realm", realmIgnoredProperties)) + .registerEntity(new EntityDefinition(ClientRepresentation.class, "clientId", + List.of("id", "authorizationSettings", "protocolMappers"))) + .registerEntity(new EntityDefinition(ProtocolMapperRepresentation.class, "name", List.of("id"))) + .registerEntity(new EntityDefinition(ClientScopeRepresentation.class, "name", List.of("id", "protocolMappers"))) + .registerEntity(new EntityDefinition(RoleRepresentation.class, "name", List.of("id", "containerId", "composites", "attributes"))) + .registerEntity(new EntityDefinition(GroupRepresentation.class, "path", List.of("id", "subGroups", "attributes", "clientRoles"))) + .registerEntity(new EntityDefinition(AuthenticationFlowRepresentation.class, "alias", List.of("id", "authenticationExecutions"))) + .registerEntity(new EntityDefinition(IdentityProviderRepresentation.class, "alias", List.of("internalId"))) + .registerEntity(EntityDefinitionBuilder.entityDefinition(IdentityProviderMapperRepresentation.class) + .withIdPropertyNames("name", "identityProviderAlias") + .withIgnoredProperties("id").build()) + .registerEntity(new EntityDefinition(RequiredActionProviderRepresentation.class, "alias")) + .registerEntity(new EntityDefinition(UserFederationProviderRepresentation.class, "displayName", List.of("id"))) + .registerEntity(EntityDefinitionBuilder.entityDefinition(UserFederationMapperRepresentation.class) + .withIdPropertyNames("name", "federationProviderDisplayName") + .withIgnoredProperties("id").build()) + .registerEntity(new EntityDefinition(ComponentExportRepresentation.class, "name", List.of("id", "subComponents", "config"))); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/exception/NormalizationException.java b/src/main/java/de/adorsys/keycloak/config/exception/NormalizationException.java new file mode 100644 index 000000000..6261834b8 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/exception/NormalizationException.java @@ -0,0 +1,31 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.exception; + +public class NormalizationException extends RuntimeException { + public NormalizationException(String message, Throwable cause) { + super(message, cause); + } + + public NormalizationException(String message) { + super(message); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/factory/UsedAuthenticationFlowWorkaroundFactory.java b/src/main/java/de/adorsys/keycloak/config/factory/UsedAuthenticationFlowWorkaroundFactory.java index c1aa21641..083871587 100644 --- a/src/main/java/de/adorsys/keycloak/config/factory/UsedAuthenticationFlowWorkaroundFactory.java +++ b/src/main/java/de/adorsys/keycloak/config/factory/UsedAuthenticationFlowWorkaroundFactory.java @@ -34,11 +34,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.*; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class UsedAuthenticationFlowWorkaroundFactory { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/model/AuthenticationFlowImport.java b/src/main/java/de/adorsys/keycloak/config/model/AuthenticationFlowImport.java index 01c046ced..8eba514ba 100644 --- a/src/main/java/de/adorsys/keycloak/config/model/AuthenticationFlowImport.java +++ b/src/main/java/de/adorsys/keycloak/config/model/AuthenticationFlowImport.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation; import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.io.Serializable; @@ -34,6 +35,7 @@ */ @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class AuthenticationFlowImport extends AuthenticationFlowRepresentation { private static final Comparator COMPARATOR = new AuthenticationExecutionExportRepresentationComparator(); diff --git a/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java b/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java index 33ac1e157..a6f86cc19 100644 --- a/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java +++ b/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java @@ -25,6 +25,7 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.userprofile.config.UPConfig; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -32,6 +33,7 @@ import java.util.Map; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RealmImport extends RealmRepresentation { private List authenticationFlowImports; diff --git a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java index a9ca479f1..3e84838ba 100644 --- a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java +++ b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java @@ -21,6 +21,7 @@ package de.adorsys.keycloak.config.properties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.DefaultValue; import org.springframework.validation.annotation.Validated; import java.util.Collection; @@ -61,10 +62,14 @@ public class ImportConfigProperties { @Valid private final ImportRemoteStateProperties remoteState; - public ImportConfigProperties(boolean validate, boolean parallel, - ImportFilesProperties files, ImportVarSubstitutionProperties varSubstitution, - ImportBehaviorsProperties behaviors, ImportCacheProperties cache, ImportManagedProperties managed, - ImportRemoteStateProperties remoteState + public ImportConfigProperties(@DefaultValue("true") boolean validate, + @DefaultValue("false") boolean parallel, + @DefaultValue ImportFilesProperties files, + @DefaultValue ImportVarSubstitutionProperties varSubstitution, + @DefaultValue ImportBehaviorsProperties behaviors, + @DefaultValue ImportCacheProperties cache, + @DefaultValue ImportManagedProperties managed, + @DefaultValue ImportRemoteStateProperties remoteState ) { this.validate = validate; this.parallel = parallel; @@ -158,16 +163,22 @@ public static class ImportManagedProperties { @NotNull private final ImportManagedPropertiesValues messageBundles; - public ImportManagedProperties(ImportManagedPropertiesValues requiredAction, ImportManagedPropertiesValues group, - ImportManagedPropertiesValues clientScope, ImportManagedPropertiesValues scopeMapping, - ImportManagedPropertiesValues clientScopeMapping, ImportManagedPropertiesValues component, - ImportManagedPropertiesValues subComponent, ImportManagedPropertiesValues authenticationFlow, - ImportManagedPropertiesValues identityProvider, ImportManagedPropertiesValues identityProviderMapper, - ImportManagedPropertiesValues role, ImportManagedPropertiesValues client, - ImportManagedPropertiesValues clientAuthorizationResources, - ImportManagedPropertiesValues clientAuthorizationPolicies, - ImportManagedPropertiesValues clientAuthorizationScopes, - ImportManagedPropertiesValues messageBundles) { + public ImportManagedProperties(@DefaultValue("FULL") ImportManagedPropertiesValues requiredAction, + @DefaultValue("FULL") ImportManagedPropertiesValues group, + @DefaultValue("FULL") ImportManagedPropertiesValues clientScope, + @DefaultValue("FULL") ImportManagedPropertiesValues scopeMapping, + @DefaultValue("FULL") ImportManagedPropertiesValues clientScopeMapping, + @DefaultValue("FULL") ImportManagedPropertiesValues component, + @DefaultValue("FULL") ImportManagedPropertiesValues subComponent, + @DefaultValue("FULL") ImportManagedPropertiesValues authenticationFlow, + @DefaultValue("FULL") ImportManagedPropertiesValues identityProvider, + @DefaultValue("FULL") ImportManagedPropertiesValues identityProviderMapper, + @DefaultValue("FULL") ImportManagedPropertiesValues role, + @DefaultValue("FULL") ImportManagedPropertiesValues client, + @DefaultValue("FULL") ImportManagedPropertiesValues clientAuthorizationResources, + @DefaultValue("FULL") ImportManagedPropertiesValues clientAuthorizationPolicies, + @DefaultValue("FULL") ImportManagedPropertiesValues clientAuthorizationScopes, + @DefaultValue("FULL") ImportManagedPropertiesValues messageBundles) { this.requiredAction = requiredAction; this.group = group; this.clientScope = clientScope; @@ -266,7 +277,9 @@ public static class ImportFilesProperties { @NotNull private final boolean includeHiddenFiles; - public ImportFilesProperties(Collection locations, Collection excludes, boolean includeHiddenFiles) { + public ImportFilesProperties(Collection locations, + @DefaultValue Collection excludes, + @DefaultValue("false") boolean includeHiddenFiles) { this.locations = locations; this.excludes = excludes; this.includeHiddenFiles = includeHiddenFiles; @@ -302,7 +315,11 @@ public static class ImportVarSubstitutionProperties { @NotNull private final String suffix; - public ImportVarSubstitutionProperties(boolean enabled, boolean nested, boolean undefinedIsError, String prefix, String suffix) { + public ImportVarSubstitutionProperties(@DefaultValue("false") boolean enabled, + @DefaultValue("true") boolean nested, + @DefaultValue("true") boolean undefinedIsError, + @DefaultValue("$(") String prefix, + @DefaultValue(")") String suffix) { this.enabled = enabled; this.nested = nested; this.undefinedIsError = undefinedIsError; @@ -390,7 +407,8 @@ public static class ImportCacheProperties { @NotNull private final String key; - public ImportCacheProperties(boolean enabled, String key) { + public ImportCacheProperties(@DefaultValue("true") boolean enabled, + @DefaultValue("default") String key) { this.enabled = enabled; this.key = key; } @@ -414,7 +432,9 @@ public static class ImportRemoteStateProperties { @Pattern(regexp = "^[A-Fa-f0-9]+$") private final String encryptionSalt; - public ImportRemoteStateProperties(boolean enabled, String encryptionKey, String encryptionSalt) { + public ImportRemoteStateProperties(@DefaultValue("true") boolean enabled, + String encryptionKey, + @DefaultValue("2B521C795FBE2F2425DB150CD3700BA9") String encryptionSalt) { this.enabled = enabled; this.encryptionKey = encryptionKey; this.encryptionSalt = encryptionSalt; diff --git a/src/main/java/de/adorsys/keycloak/config/properties/KeycloakConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/KeycloakConfigProperties.java index 0dc8339de..a188db216 100644 --- a/src/main/java/de/adorsys/keycloak/config/properties/KeycloakConfigProperties.java +++ b/src/main/java/de/adorsys/keycloak/config/properties/KeycloakConfigProperties.java @@ -21,6 +21,7 @@ package de.adorsys.keycloak.config.properties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.DefaultValue; import org.springframework.validation.annotation.Validated; import java.net.URL; @@ -69,19 +70,19 @@ public class KeycloakConfigProperties { private final KeycloakAvailabilityCheck availabilityCheck; public KeycloakConfigProperties( - String loginRealm, - String clientId, + @DefaultValue("master") String loginRealm, + @DefaultValue("admin-cli") String clientId, String version, String url, - String user, + @DefaultValue("admin") String user, String password, - String clientSecret, - String grantType, - boolean sslVerify, + @DefaultValue("") String clientSecret, + @DefaultValue("password") String grantType, + @DefaultValue("true") boolean sslVerify, URL httpProxy, - KeycloakAvailabilityCheck availabilityCheck, - Duration connectTimeout, - Duration readTimeout + @DefaultValue KeycloakAvailabilityCheck availabilityCheck, + @DefaultValue("10s") Duration connectTimeout, + @DefaultValue("10s") Duration readTimeout ) { this.loginRealm = loginRealm; this.clientId = clientId; @@ -161,7 +162,9 @@ public static class KeycloakAvailabilityCheck { private final Duration retryDelay; @SuppressWarnings("unused") - public KeycloakAvailabilityCheck(boolean enabled, Duration timeout, Duration retryDelay) { + public KeycloakAvailabilityCheck(@DefaultValue("false") boolean enabled, + @DefaultValue("120s") Duration timeout, + @DefaultValue("2s") Duration retryDelay) { this.enabled = enabled; this.timeout = timeout; this.retryDelay = retryDelay; diff --git a/src/main/java/de/adorsys/keycloak/config/properties/NormalizationConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/NormalizationConfigProperties.java new file mode 100644 index 000000000..07a898055 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/properties/NormalizationConfigProperties.java @@ -0,0 +1,107 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.DefaultValue; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; + +@ConfigurationProperties(prefix = "normalization", ignoreUnknownFields = false) +@Validated +public class NormalizationConfigProperties { + + @Valid + private final NormalizationFilesProperties files; + + private final OutputFormat outputFormat; + + private final String fallbackVersion; + + public NormalizationConfigProperties(@DefaultValue NormalizationFilesProperties files, + @DefaultValue("yaml") OutputFormat outputFormat, + String fallbackVersion) { + this.files = files; + this.outputFormat = outputFormat; + this.fallbackVersion = fallbackVersion; + } + + public NormalizationFilesProperties getFiles() { + return files; + } + + public OutputFormat getOutputFormat() { + return outputFormat; + } + + public String getFallbackVersion() { + return fallbackVersion; + } + + public static class NormalizationFilesProperties { + + @NotNull + private final Collection inputLocations; + + @NotNull + private final Collection excludes; + + @NotNull + private final boolean includeHiddenFiles; + + @NotNull + private final String outputDirectory; + + public NormalizationFilesProperties(Collection inputLocations, + @DefaultValue Collection excludes, + @DefaultValue("false") boolean includeHiddenFiles, + String outputDirectory) { + this.inputLocations = inputLocations; + this.excludes = excludes; + this.includeHiddenFiles = includeHiddenFiles; + this.outputDirectory = outputDirectory; + } + + public Collection getInputLocations() { + return inputLocations; + } + + public Collection getExcludes() { + return excludes; + } + + public boolean isIncludeHiddenFiles() { + return includeHiddenFiles; + } + + public String getOutputDirectory() { + return outputDirectory; + } + } + + public enum OutputFormat { + JSON, YAML + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/properties/NormalizationKeycloakConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/NormalizationKeycloakConfigProperties.java new file mode 100644 index 000000000..c11edb36e --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/properties/NormalizationKeycloakConfigProperties.java @@ -0,0 +1,47 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import jakarta.validation.constraints.NotNull; + +/* + * Duplicated prefix keycloak. Since only one of the two classes is loaded (depending on configuration) this is fine. + * This saves us from having to define a keycloak address for the normalization usage, since we don't actually need to + * talk to a keycloak instance, and we only need to know the version. + */ +@ConfigurationProperties(prefix = "normalize", ignoreUnknownFields = false) +@Validated +public class NormalizationKeycloakConfigProperties { + + @NotNull + private final String version; + + public NormalizationKeycloakConfigProperties(String version) { + this.version = version; + } + + public String getVersion() { + return version; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/properties/RunConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/RunConfigProperties.java new file mode 100644 index 000000000..ede1713bb --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/properties/RunConfigProperties.java @@ -0,0 +1,44 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.DefaultValue; +import org.springframework.validation.annotation.Validated; + +@ConfigurationProperties(prefix = "run", ignoreUnknownFields = false) +@Validated +public class RunConfigProperties { + + private final Operation operation; + + public RunConfigProperties(@DefaultValue("IMPORT") Operation operation) { + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } + + public enum Operation { + IMPORT, NORMALIZE + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/provider/BaselineProvider.java b/src/main/java/de/adorsys/keycloak/config/provider/BaselineProvider.java new file mode 100644 index 000000000..f2722a904 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/provider/BaselineProvider.java @@ -0,0 +1,111 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.provider; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.adorsys.keycloak.config.exception.NormalizationException; +import de.adorsys.keycloak.config.properties.NormalizationConfigProperties; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +@Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class BaselineProvider { + + private static final Logger logger = LoggerFactory.getLogger(BaselineProvider.class); + private static final String PLACEHOLDER = "REALM_NAME_PLACEHOLDER"; + + private final ObjectMapper objectMapper; + + private final String fallbackVersion; + + @Autowired + public BaselineProvider(ObjectMapper objectMapper, NormalizationConfigProperties normalizationConfigProperties) { + this.objectMapper = objectMapper; + this.fallbackVersion = normalizationConfigProperties.getFallbackVersion(); + } + + public RealmRepresentation getRealm(String version, String realmName) { + try (var inputStream = getRealmInputStream(version)) { + /* + * Replace the placeholder with the realm name to import. This sets some internal values like role names, + * baseUrls and redirectUrls so that they don't get picked up as "changes" + */ + var realmString = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8).replace(PLACEHOLDER, realmName); + return objectMapper.readValue(realmString, RealmRepresentation.class); + } catch (IOException ex) { + throw new NormalizationException(String.format("Failed to load baseline realm for version %s", version), ex); + } + } + + public ClientRepresentation getClient(String version, String clientId) { + try (var is = getClientInputStream(version)) { + var client = objectMapper.readValue(is, ClientRepresentation.class); + client.setClientId(clientId); + return client; + } catch (IOException ex) { + throw new NormalizationException(String.format("Failed to load baseline client for version %s", version), ex); + } + } + + public InputStream getRealmInputStream(String version) { + var inputStream = getClass().getResourceAsStream(String.format("/baseline/%s/realm/realm.json", version)); + if (inputStream == null) { + if (fallbackVersion != null) { + logger.warn("Reference realm not found for version {}. Using fallback version {}!", version, fallbackVersion); + inputStream = getClass().getResourceAsStream(String.format("/baseline/%s/realm/realm.json", fallbackVersion)); + if (inputStream == null) { + throw new NormalizationException(String.format("Reference realm for version %s does not exist, " + + "and fallback version %s does not exist either. Aborting!", version, fallbackVersion)); + } + } else { + throw new NormalizationException(String.format("Reference realm for version %s does not exist. Aborting!", version)); + } + } + return inputStream; + } + + public InputStream getClientInputStream(String version) { + var inputStream = getClass().getResourceAsStream(String.format("/baseline/%s/client/client.json", version)); + if (inputStream == null) { + if (fallbackVersion != null) { + logger.debug("Reference client not found for version {}. Using fallback version {}!", version, fallbackVersion); + inputStream = getClass().getResourceAsStream(String.format("/baseline/%s/client/client.json", fallbackVersion)); + if (inputStream == null) { + throw new NormalizationException(String.format("Reference client for version %s does not exist, " + + "and fallback version %s does not exist either. Aborting!", version, fallbackVersion)); + } + } else { + throw new NormalizationException(String.format("Reference client for version %s does not exist. Aborting!", version)); + } + } + return inputStream; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/provider/KeycloakExportProvider.java b/src/main/java/de/adorsys/keycloak/config/provider/KeycloakExportProvider.java new file mode 100644 index 000000000..c64c00a2e --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/provider/KeycloakExportProvider.java @@ -0,0 +1,232 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.provider; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.adorsys.keycloak.config.exception.InvalidImportException; +import de.adorsys.keycloak.config.model.ImportResource; +import de.adorsys.keycloak.config.properties.NormalizationConfigProperties; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.keycloak.representations.idm.RealmRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.stereotype.Component; +import org.springframework.util.PathMatcher; +import org.yaml.snakeyaml.Yaml; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +/* + * This class heavily copy pastes code from KeycloakImportProvider. This can probably be reduced quite a bit by moving some code out to a shared class + */ +@Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class KeycloakExportProvider { + + private static final Logger logger = LoggerFactory.getLogger(KeycloakExportProvider.class); + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() + .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + private final PathMatchingResourcePatternResolver patternResolver; + + private final NormalizationConfigProperties normalizationConfigProperties; + + @Autowired + public KeycloakExportProvider(PathMatchingResourcePatternResolver patternResolver, + NormalizationConfigProperties normalizationConfigProperties) { + this.patternResolver = patternResolver; + this.normalizationConfigProperties = normalizationConfigProperties; + } + + public Map>> readFromLocations() { + Map>> files = new LinkedHashMap<>(); + + for (String location : normalizationConfigProperties.getFiles().getInputLocations()) { + logger.debug("Loading file location '{}'", location); + String resourceLocation = prepareResourceLocation(location); + + Resource[] resources; + try { + resources = this.patternResolver.getResources(resourceLocation); + } catch (IOException e) { + throw new InvalidImportException("Unable to proceed location '" + location + "': " + e.getMessage(), e); + } + + resources = Arrays.stream(resources).filter(this::filterExcludedResources).toArray(Resource[]::new); + + if (resources.length == 0) { + throw new InvalidImportException("No files matching '" + location + "'!"); + } + + Map> exports = Arrays.stream(resources) + .map(this::readResource) + .filter(this::filterEmptyResources) + .sorted(Map.Entry.comparingByKey()) + .map(this::readRealms) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, + (oldValue, newValue) -> oldValue, LinkedHashMap::new)); + files.put(location, exports); + } + return files; + } + + private Pair> readRealms(ImportResource resource) { + String location = resource.getFilename(); + String content = resource.getValue(); + + if (logger.isTraceEnabled()) { + logger.trace(content); + } + + List realms; + try { + realms = readContent(content); + } catch (Exception e) { + throw new InvalidImportException("Unable to parse file '" + location + "': " + e.getMessage(), e); + } + return new ImmutablePair<>(location, realms); + } + + private List readContent(String content) { + List realms = new ArrayList<>(); + + Yaml yaml = new Yaml(); + Iterable yamlDocuments = yaml.loadAll(content); + + for (Object yamlDocument : yamlDocuments) { + realms.add(OBJECT_MAPPER.convertValue(yamlDocument, RealmRepresentation.class)); + } + return realms; + } + + private String prepareResourceLocation(String location) { + String importLocation = location; + + importLocation = importLocation.replaceFirst("^zip:", "jar:"); + + // backward compatibility to correct a possible missing prefix "file:" in path + if (!importLocation.contains(":")) { + importLocation = "file:" + importLocation; + } + return importLocation; + } + + private boolean filterExcludedResources(Resource resource) { + if (!resource.isFile()) { + return true; + } + + File file; + + try { + file = resource.getFile(); + } catch (IOException ignored) { + return true; + } + + if (file.isDirectory()) { + return false; + } + + if (!this.normalizationConfigProperties.getFiles().isIncludeHiddenFiles() + && (file.isHidden() || FileUtils.hasHiddenAncestorDirectory(file))) { + return false; + } + + PathMatcher pathMatcher = patternResolver.getPathMatcher(); + return normalizationConfigProperties.getFiles().getExcludes() + .stream() + .map(pattern -> pattern.startsWith("**") ? "/" + pattern : pattern) + .map(pattern -> !pattern.startsWith("/**") ? "/**" + pattern : pattern) + .map(pattern -> !pattern.startsWith("/") ? "/" + pattern : pattern) + .noneMatch(pattern -> { + boolean match = pathMatcher.match(pattern, file.getPath()); + if (match) { + logger.debug("Excluding resource file '{}' (match {})", file.getPath(), pattern); + return true; + } + return false; + }); + } + + private ImportResource readResource(Resource resource) { + logger.debug("Loading file '{}'", resource.getFilename()); + + try { + resource = setupAuthentication(resource); + try (InputStream inputStream = resource.getInputStream()) { + return new ImportResource(resource.getURI().toString(), new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)); + } + } catch (IOException e) { + throw new InvalidImportException("Unable to proceed resource '" + resource + "': " + e.getMessage(), e); + } finally { + Authenticator.setDefault(null); + } + } + + private Resource setupAuthentication(Resource resource) throws IOException { + String userInfo; + + try { + userInfo = resource.getURL().getUserInfo(); + } catch (IOException e) { + return resource; + } + + if (userInfo == null) return resource; + + String[] userInfoSplit = userInfo.split(":"); + + if (userInfoSplit.length != 2) return resource; + + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(userInfoSplit[0], userInfoSplit[1].toCharArray()); + } + }); + + // Mask AuthInfo + String location = resource.getURI().toString().replace(userInfo + "@", "***@"); + return new UrlResource(location); + } + + private boolean filterEmptyResources(ImportResource resource) { + return !resource.getValue().isEmpty(); + } + + +} diff --git a/src/main/java/de/adorsys/keycloak/config/provider/KeycloakImportProvider.java b/src/main/java/de/adorsys/keycloak/config/provider/KeycloakImportProvider.java index 13506aefa..f8c025ed0 100644 --- a/src/main/java/de/adorsys/keycloak/config/provider/KeycloakImportProvider.java +++ b/src/main/java/de/adorsys/keycloak/config/provider/KeycloakImportProvider.java @@ -36,6 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.core.env.Environment; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; @@ -54,6 +55,7 @@ import java.util.stream.Collectors; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class KeycloakImportProvider { private final PathMatchingResourcePatternResolver patternResolver; private final ImportConfigProperties importConfigProperties; diff --git a/src/main/java/de/adorsys/keycloak/config/provider/KeycloakProvider.java b/src/main/java/de/adorsys/keycloak/config/provider/KeycloakProvider.java index 20be19461..e76f5e59f 100644 --- a/src/main/java/de/adorsys/keycloak/config/provider/KeycloakProvider.java +++ b/src/main/java/de/adorsys/keycloak/config/provider/KeycloakProvider.java @@ -33,6 +33,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.net.URI; @@ -51,6 +52,7 @@ * to avoid a deadlock. */ @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class KeycloakProvider implements AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(KeycloakProvider.class); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/AuthenticationFlowRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/AuthenticationFlowRepository.java index 959f68d12..69989a2ec 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/AuthenticationFlowRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/AuthenticationFlowRepository.java @@ -32,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.springframework.util.Assert; @@ -45,6 +46,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class AuthenticationFlowRepository { private static final Logger logger = LoggerFactory.getLogger(AuthenticationFlowRepository.class); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/AuthenticatorConfigRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/AuthenticatorConfigRepository.java index 10107cbc4..b9849fb46 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/AuthenticatorConfigRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/AuthenticatorConfigRepository.java @@ -24,12 +24,14 @@ import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class AuthenticatorConfigRepository { private final AuthenticationFlowRepository authenticationFlowRepository; private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java index 5fe290ecd..551323d13 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ClientPoliciesRepository.java @@ -28,9 +28,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientPoliciesRepository { private static final Logger logger = LoggerFactory.getLogger(ClientPoliciesRepository.class); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java index 8b89e4a47..e4a159009 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ClientRepository.java @@ -35,6 +35,7 @@ import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; import org.keycloak.representations.idm.authorization.ScopeRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -47,6 +48,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ClientScopeRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ClientScopeRepository.java index a5a8bdaa1..239daa9eb 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ClientScopeRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ClientScopeRepository.java @@ -29,6 +29,7 @@ import org.keycloak.representations.idm.ClientScopeRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -40,6 +41,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientScopeRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java index 388f05073..0ee803767 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java @@ -28,6 +28,7 @@ import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.representations.idm.ComponentRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.Collections; @@ -39,6 +40,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ComponentRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ExecutionFlowRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ExecutionFlowRepository.java index a806e06a3..8aae2acd1 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ExecutionFlowRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ExecutionFlowRepository.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.HashMap; @@ -42,6 +43,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ExecutionFlowRepository { private static final Logger logger = LoggerFactory.getLogger(ExecutionFlowRepository.class); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java index ad3227c35..662a196f4 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/GroupRepository.java @@ -32,6 +32,7 @@ import org.keycloak.representations.idm.ManagementPermissionRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -42,6 +43,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class GroupRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderMapperRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderMapperRepository.java index 84563091b..7d557a464 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderMapperRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderMapperRepository.java @@ -26,6 +26,7 @@ import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -36,6 +37,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class IdentityProviderMapperRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderRepository.java index 14c89315c..f5cd3fcba 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/IdentityProviderRepository.java @@ -28,6 +28,7 @@ import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.idm.ManagementPermissionRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -37,6 +38,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class IdentityProviderRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/OtpPolicyRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/OtpPolicyRepository.java index def03b1ec..3f236f7da 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/OtpPolicyRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/OtpPolicyRepository.java @@ -22,9 +22,11 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class OtpPolicyRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/RealmRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/RealmRepository.java index 8a6d44c48..4e2d94220 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/RealmRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/RealmRepository.java @@ -28,12 +28,16 @@ import org.keycloak.admin.client.resource.RealmsResource; import org.keycloak.representations.idm.RealmRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import java.util.List; + import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.WebApplicationException; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RealmRepository { private final KeycloakProvider keycloakProvider; @@ -106,4 +110,8 @@ public void removeDefaultDefaultClientScope(String realmName, String scopeId) { public void removeDefaultOptionalClientScope(String realmName, String scopeId) { getResource(realmName).removeDefaultOptionalClientScope(scopeId); } + + public List getRealms() { + return keycloakProvider.getInstance().realms().findAll(); + } } diff --git a/src/main/java/de/adorsys/keycloak/config/repository/RequiredActionRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/RequiredActionRepository.java index b6d91be12..d3801dd47 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/RequiredActionRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/RequiredActionRepository.java @@ -25,6 +25,7 @@ import org.keycloak.representations.idm.RequiredActionProviderRepresentation; import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -36,6 +37,7 @@ * Provides methods to retrieve and store required-actions in your realm */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RequiredActionRepository { private final AuthenticationFlowRepository authenticationFlowRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java index 6eee79b85..7c831c33c 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/RoleCompositeRepository.java @@ -26,6 +26,7 @@ import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.*; @@ -33,6 +34,7 @@ import java.util.stream.Collectors; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RoleCompositeRepository { private final RoleRepository roleRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java index b72397dab..43439ccbf 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/RoleRepository.java @@ -27,6 +27,7 @@ import org.keycloak.admin.client.resource.*; import org.keycloak.representations.idm.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; @@ -36,6 +37,7 @@ import jakarta.ws.rs.NotFoundException; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RoleRepository { private final RealmRepository realmRepository; private final ClientRepository clientRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ScopeMappingRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ScopeMappingRepository.java index 7578129ab..0ae7a37a7 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ScopeMappingRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ScopeMappingRepository.java @@ -26,6 +26,7 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.ScopeMappingRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.Collection; @@ -33,6 +34,7 @@ import java.util.Objects; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ScopeMappingRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java index 212ab611f..38679f63f 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java @@ -24,6 +24,7 @@ import de.adorsys.keycloak.config.properties.ImportConfigProperties; import de.adorsys.keycloak.config.util.CryptoUtil; import org.keycloak.representations.idm.RealmRepresentation; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.text.MessageFormat; @@ -36,6 +37,7 @@ import static de.adorsys.keycloak.config.util.JsonUtil.toJson; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class StateRepository { private static final int MAX_ATTRIBUTE_LENGTH = 250; diff --git a/src/main/java/de/adorsys/keycloak/config/repository/UserProfileRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/UserProfileRepository.java index ceee55568..3d4af81a1 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/UserProfileRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/UserProfileRepository.java @@ -27,10 +27,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class UserProfileRepository { private static final Logger logger = LoggerFactory.getLogger(UserProfileRepository.class); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/UserRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/UserRepository.java index e6ba35d2a..640ece584 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/UserRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/UserRepository.java @@ -28,6 +28,7 @@ import org.keycloak.representations.idm.GroupRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -36,6 +37,7 @@ import jakarta.ws.rs.core.Response; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class UserRepository { private final RealmRepository realmRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java index 9de2e9cef..a47fa2037 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java @@ -35,6 +35,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -53,6 +54,7 @@ * sub-flow: any flow which has the property 'topLevel' set to 'false' and which are related to execution-flows within topLevel-flows */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class AuthenticationFlowsImportService { private static final Logger logger = LoggerFactory.getLogger(AuthenticationFlowsImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java b/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java index c4a6aa4e5..dc60cba1e 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java @@ -29,6 +29,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -39,6 +40,7 @@ import java.util.stream.Stream; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class AuthenticatorConfigImportService { private static final Logger logger = LoggerFactory.getLogger(AuthenticatorConfigImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java index 5532832f3..b3ab46000 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientAuthorizationImportService.java @@ -45,6 +45,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.HashMap; @@ -60,6 +61,7 @@ @Service @SuppressWarnings({"java:S1192"}) +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientAuthorizationImportService { private static final Logger logger = LoggerFactory.getLogger(ClientAuthorizationImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java index 92b0b26f8..ae59dfcdd 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientImportService.java @@ -39,6 +39,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.*; @@ -52,6 +53,7 @@ @Service @SuppressWarnings({"java:S1192"}) +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientImportService { private static final Logger logger = LoggerFactory.getLogger(ClientImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java index 6522bc24a..337f5089e 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientPoliciesImportService.java @@ -29,9 +29,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientPoliciesImportService { private static final Logger logger = LoggerFactory.getLogger(ClientPoliciesImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java index d242a73da..b93ea5b6d 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientScopeImportService.java @@ -32,6 +32,7 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -40,6 +41,7 @@ import java.util.function.Consumer; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientScopeImportService { private static final Logger logger = LoggerFactory.getLogger(ClientScopeImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/ClientScopeMappingImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ClientScopeMappingImportService.java index 73eea8a76..305bb3aa9 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ClientScopeMappingImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ClientScopeMappingImportService.java @@ -32,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -41,6 +42,7 @@ import java.util.function.Predicate; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientScopeMappingImportService { private static final Logger logger = LoggerFactory.getLogger(ClientScopeMappingImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java index 586283ab2..0d8bd3042 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java @@ -34,11 +34,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.*; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ComponentImportService { private static final Logger logger = LoggerFactory.getLogger(ComponentImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/DefaultGroupsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/DefaultGroupsImportService.java index e10f91849..3c9aedce2 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/DefaultGroupsImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/DefaultGroupsImportService.java @@ -26,6 +26,7 @@ import de.adorsys.keycloak.config.repository.RealmRepository; import org.keycloak.admin.client.resource.RealmResource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -33,6 +34,7 @@ import jakarta.ws.rs.NotFoundException; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class DefaultGroupsImportService { private final RealmRepository realmRepository; private final GroupRepository groupRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java index de40b5cd6..59c1d1f9b 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.HashMap; @@ -44,6 +45,7 @@ * Imports executions and execution-flows of existing top-level flows */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ExecutionFlowsImportService { private static final Logger logger = LoggerFactory.getLogger(ExecutionFlowsImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java b/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java index e40637026..013a160fe 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java @@ -30,6 +30,7 @@ import org.keycloak.representations.idm.GroupRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -38,6 +39,7 @@ import java.util.stream.Collectors; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class GroupImportService { private static final Logger logger = LoggerFactory.getLogger(GroupImportService.class); private static final int LOAD_CREATED_GROUP_MAX_RETRIES = 5; diff --git a/src/main/java/de/adorsys/keycloak/config/service/IdentityProviderImportService.java b/src/main/java/de/adorsys/keycloak/config/service/IdentityProviderImportService.java index d2dbfb63e..a444e14a2 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/IdentityProviderImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/IdentityProviderImportService.java @@ -30,6 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -39,6 +40,7 @@ import static de.adorsys.keycloak.config.properties.ImportConfigProperties.ImportManagedProperties.ImportManagedPropertiesValues; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class IdentityProviderImportService { private static final Logger logger = LoggerFactory.getLogger(IdentityProviderImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/MessageBundleImportService.java b/src/main/java/de/adorsys/keycloak/config/service/MessageBundleImportService.java index 5d415ba90..922ebcba2 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/MessageBundleImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/MessageBundleImportService.java @@ -29,6 +29,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -39,6 +40,7 @@ * Creates and updates message bundles in your realm */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class MessageBundleImportService { private static final Logger logger = LoggerFactory.getLogger(MessageBundleImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/OtpPolicyImportService.java b/src/main/java/de/adorsys/keycloak/config/service/OtpPolicyImportService.java index 20ba43f56..f958781ad 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/OtpPolicyImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/OtpPolicyImportService.java @@ -23,9 +23,11 @@ import de.adorsys.keycloak.config.repository.OtpPolicyRepository; import org.keycloak.representations.idm.RealmRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class OtpPolicyImportService { private final OtpPolicyRepository otpPolicyRepository; diff --git a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java index c1af0878e..14c31518c 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java @@ -31,9 +31,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RealmImportService { static final String[] ignoredPropertiesForRealmImport = new String[]{ "authenticatorConfig", diff --git a/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java index 602c0db55..1cc001119 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java @@ -30,6 +30,7 @@ import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -40,6 +41,7 @@ * Creates and updates required-actions in your realm */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RequiredActionsImportService { private static final Logger logger = LoggerFactory.getLogger(RequiredActionsImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/RoleImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RoleImportService.java index 745e7cdb9..447e6815e 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/RoleImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/RoleImportService.java @@ -34,6 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -44,6 +45,7 @@ import java.util.stream.Collectors; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RoleImportService { private static final Logger logger = LoggerFactory.getLogger(RoleImportService.class); private static final String[] propertiesWithDependencies = new String[]{ diff --git a/src/main/java/de/adorsys/keycloak/config/service/ScopeMappingImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ScopeMappingImportService.java index aab449917..602eca15c 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ScopeMappingImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ScopeMappingImportService.java @@ -30,6 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -38,6 +39,7 @@ import java.util.Set; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ScopeMappingImportService { private static final Logger logger = LoggerFactory.getLogger(ScopeMappingImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/UserImportService.java b/src/main/java/de/adorsys/keycloak/config/service/UserImportService.java index 595805013..031409269 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/UserImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/UserImportService.java @@ -34,6 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -42,6 +43,7 @@ import java.util.stream.Collectors; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class UserImportService { private static final Logger logger = LoggerFactory.getLogger(UserImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/UserProfileImportService.java b/src/main/java/de/adorsys/keycloak/config/service/UserProfileImportService.java index 48ee64525..95fac2fa7 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/UserProfileImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/UserProfileImportService.java @@ -26,9 +26,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class UserProfileImportService { private static final Logger logger = LoggerFactory.getLogger(UserProfileImportService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/checksum/ChecksumService.java b/src/main/java/de/adorsys/keycloak/config/service/checksum/ChecksumService.java index 87bd7b21a..2cd98d18d 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/checksum/ChecksumService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/checksum/ChecksumService.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.text.MessageFormat; @@ -38,6 +39,7 @@ import java.util.Objects; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ChecksumService { private static final Logger logger = LoggerFactory.getLogger(ChecksumService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/AttributeNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/AttributeNormalizationService.java new file mode 100644 index 000000000..267faab0d --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/AttributeNormalizationService.java @@ -0,0 +1,96 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.*; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class AttributeNormalizationService { + + private final Javers unOrderedJavers; + + public AttributeNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public Map normalizeStringAttributes(Map exportedAttributes, Map baselineAttributes) { + var exportedOrEmpty = getNonNull(exportedAttributes); + var baselineOrEmpty = getNonNull(baselineAttributes); + var normalizedAttributes = new HashMap(); + for (var entry : baselineOrEmpty.entrySet()) { + var attributeName = entry.getKey(); + var baselineAttribute = entry.getValue(); + var exportedAttribute = exportedOrEmpty.remove(attributeName); + + if (!Objects.equals(baselineAttribute, exportedAttribute)) { + normalizedAttributes.put(attributeName, exportedAttribute); + } + } + normalizedAttributes.putAll(exportedOrEmpty); + return normalizedAttributes.isEmpty() ? null : normalizedAttributes; + } + + public Map> normalizeListAttributes(Map> exportedAttributes, + Map> baselineAttributes) { + var exportedOrEmpty = getNonNull(exportedAttributes); + var baselineOrEmpty = getNonNull(baselineAttributes); + var normalizedAttributes = new HashMap>(); + for (var entry : baselineOrEmpty.entrySet()) { + var attributeName = entry.getKey(); + var baselineAttribute = entry.getValue(); + var exportedAttribute = exportedOrEmpty.remove(attributeName); + + if (unOrderedJavers.compareCollections(baselineAttribute, exportedAttribute, String.class).hasChanges()) { + normalizedAttributes.put(attributeName, exportedAttribute); + } + } + normalizedAttributes.putAll(exportedOrEmpty); + return normalizedAttributes.isEmpty() ? null : normalizedAttributes; + } + + public boolean listAttributesChanged(Map> exportedAttributes, Map> baselineAttributes) { + var exportedOrEmpty = getNonNull(exportedAttributes); + var baselineOrEmpty = getNonNull(baselineAttributes); + + if (!Objects.equals(exportedOrEmpty.keySet(), baselineOrEmpty.keySet())) { + return true; + } + + for (var entry : baselineOrEmpty.entrySet()) { + if (unOrderedJavers.compareCollections(entry.getValue(), + exportedOrEmpty.get(entry.getKey()), String.class).hasChanges()) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationService.java new file mode 100644 index 000000000..6f00051a4 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationService.java @@ -0,0 +1,238 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.AbstractAuthenticationExecutionRepresentation; +import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; +import static java.util.function.Predicate.not; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class AuthFlowNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(AuthFlowNormalizationService.class); + + private final Javers unOrderedJavers; + + public AuthFlowNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public List normalizeAuthFlows(List exportedAuthFlows, + List baselineAuthFlows) { + var exportedFiltered = filterBuiltIn(exportedAuthFlows); + var baselineFiltered = filterBuiltIn(baselineAuthFlows); + + Map exportedMap = exportedFiltered.stream() + .collect(Collectors.toMap(AuthenticationFlowRepresentation::getAlias, Function.identity())); + Map baselineMap = baselineFiltered.stream() + .collect(Collectors.toMap(AuthenticationFlowRepresentation::getAlias, Function.identity())); + + List normalizedFlows = new ArrayList<>(); + for (var entry : baselineMap.entrySet()) { + var alias = entry.getKey(); + var exportedFlow = exportedMap.remove(alias); + if (exportedFlow == null) { + logger.warn("Default realm authentication flow '{}' was deleted in exported realm. It may be reintroduced during import", alias); + continue; + } + var baselineFlow = entry.getValue(); + var diff = unOrderedJavers.compare(baselineFlow, exportedFlow); + + if (diff.hasChanges() || executionsChanged(exportedFlow.getAuthenticationExecutions(), baselineFlow.getAuthenticationExecutions())) { + normalizedFlows.add(exportedFlow); + } + } + normalizedFlows.addAll(exportedMap.values()); + for (var flow : normalizedFlows) { + flow.setId(null); + } + normalizedFlows = filterUnusedNonTopLevel(normalizedFlows); + detectBrokenAuthenticationFlows(normalizedFlows); + return normalizedFlows.isEmpty() ? null : normalizedFlows; + } + + public void detectBrokenAuthenticationFlows(List flows) { + var flowsByAlias = flows.stream().collect(Collectors.toMap(AuthenticationFlowRepresentation::getAlias, Function.identity())); + for (var flow : flows) { + for (var execution : flow.getAuthenticationExecutions()) { + var flowAlias = execution.getFlowAlias(); + var authenticator = execution.getAuthenticator(); + + if (flowAlias != null && authenticator != null) { + var referencedFlow = flowsByAlias.get(flowAlias); + if (!"form-flow".equals(referencedFlow.getProviderId())) { + logger.error("An execution of flow '{}' defines an authenticator and references the sub-flow '{}'." + + " This is only possible if the sub-flow is of type 'form-flow', but it is of type '{}'." + + " keycloak-config-cli will refuse to import this flow. See NORMALIZE.md for more information.", + flow.getAlias(), flowAlias, referencedFlow.getProviderId()); + } + } + } + } + + } + + public List normalizeAuthConfig(List configs, + List flows) { + var flowsOrEmpty = getNonNull(flows); + // Find out which configs are actually used by the normalized flows + var usedConfigs = flowsOrEmpty.stream() + .map(AuthenticationFlowRepresentation::getAuthenticationExecutions) + .map(l -> l.stream() + .map(AbstractAuthenticationExecutionRepresentation::getAuthenticatorConfig) + .collect(Collectors.toList())).flatMap(Collection::stream) + .collect(Collectors.toSet()); + + var configOrEmpty = getNonNull(configs); + // Only return configs that are used + var filteredConfigs = configOrEmpty.stream() + .filter(acr -> usedConfigs.contains(acr.getAlias())).collect(Collectors.toList()); + + var duplicates = new HashSet(); + var seen = new HashSet(); + for (var config : filteredConfigs) { + config.setId(null); + if (seen.contains(config.getAlias())) { + duplicates.add(config.getAlias()); + } else { + seen.add(config.getAlias()); + } + } + + if (!duplicates.isEmpty()) { + logger.warn("The following authenticator configs are duplicates: {}. " + + "Check NORMALIZE.md for an SQL query to find the offending entries in your database!", duplicates); + } + + if (configs.size() != filteredConfigs.size()) { + logger.warn("Some authenticator configs are unused. Check NORMALIZE.md for an SQL query to find the offending entries in your database!"); + } + return filteredConfigs.isEmpty() ? null : filteredConfigs; + } + + private List filterBuiltIn(List flows) { + if (flows == null) { + return new ArrayList<>(); + } + return flows.stream().filter(not(AuthenticationFlowRepresentation::isBuiltIn)).collect(Collectors.toList()); + } + + private List filterUnusedNonTopLevel(List flows) { + // Assume all top level flows are used + var usedFlows = flows.stream().filter(AuthenticationFlowRepresentation::isTopLevel).collect(Collectors.toList()); + var potentialUnused = flows.stream().filter(not(AuthenticationFlowRepresentation::isTopLevel)) + .collect(Collectors.toMap(AuthenticationFlowRepresentation::getAlias, Function.identity())); + var toCheck = new ArrayList<>(usedFlows); + while (!toCheck.isEmpty()) { + var toRemove = new ArrayList(); + for (var flow : toCheck) { + for (var execution : flow.getAuthenticationExecutions()) { + var alias = execution.getFlowAlias(); + if (alias != null && potentialUnused.containsKey(alias)) { + toRemove.add(alias); + } + } + } + toCheck.clear(); + for (var alias : toRemove) { + toCheck.add(potentialUnused.remove(alias)); + } + usedFlows.addAll(toCheck); + } + if (usedFlows.size() != flows.size()) { + logger.warn("The following authentication flows are unused: {}. " + + "Check NORMALIZE.md for an SQL query to find the offending entries in your database!", potentialUnused.keySet()); + } + return usedFlows; + } + + public boolean executionsChanged(List exportedExecutions, + List baselineExecutions) { + if (exportedExecutions == null && baselineExecutions != null) { + return true; + } + + if (exportedExecutions != null && baselineExecutions == null) { + return true; + } + + if (exportedExecutions == null) { + return false; + } + + if (exportedExecutions.size() != baselineExecutions.size()) { + return true; + } + + exportedExecutions.sort(Comparator.comparing(AbstractAuthenticationExecutionRepresentation::getPriority)); + baselineExecutions.sort(Comparator.comparing(AbstractAuthenticationExecutionRepresentation::getPriority)); + + for (int i = 0; i < exportedExecutions.size(); i++) { + if (executionChanged(exportedExecutions.get(i), baselineExecutions.get(i))) { + return true; + } + } + return false; + } + + public boolean executionChanged(AuthenticationExecutionExportRepresentation exportedExecution, + AuthenticationExecutionExportRepresentation baselineExecution) { + if (!Objects.equals(exportedExecution.getAuthenticatorConfig(), baselineExecution.getAuthenticatorConfig())) { + return true; + } + if (!Objects.equals(exportedExecution.getAuthenticator(), baselineExecution.getAuthenticator())) { + return true; + } + if (!Objects.equals(exportedExecution.isAuthenticatorFlow(), baselineExecution.isAuthenticatorFlow())) { + return true; + } + if (!Objects.equals(exportedExecution.getRequirement(), baselineExecution.getRequirement())) { + return true; + } + if (!Objects.equals(exportedExecution.getPriority(), baselineExecution.getPriority())) { + return true; + } + if (!Objects.equals(exportedExecution.getFlowAlias(), baselineExecution.getFlowAlias())) { + return true; + } + return !Objects.equals(exportedExecution.isUserSetupAllowed(), baselineExecution.isUserSetupAllowed()); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientNormalizationService.java new file mode 100644 index 000000000..e36b40063 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientNormalizationService.java @@ -0,0 +1,169 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import de.adorsys.keycloak.config.provider.BaselineProvider; +import de.adorsys.keycloak.config.util.JaversUtil; +import org.javers.core.Javers; +import org.javers.core.diff.changetype.PropertyChange; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class ClientNormalizationService { + + private static final Set SAML_ATTRIBUTES = Set.of("saml_signature_canonicalization_method", "saml.onetimeuse.condition", + "saml_name_id_format", "saml.authnstatement", "saml.server.signature.keyinfo$xmlSigKeyInfoKeyNameTransformer", + "saml_force_name_id_format", "saml.artifact.binding", "saml.artifact.binding.identifier", "saml.server.signature", "saml.encrypt", + "saml.assertion.signature", "saml.allow.ecp.flow", "saml.signing.private.key", "saml.force.name.id.format", "saml.client.signature", + "saml.signature.algorithm", "saml.signing.certificate", "saml.server.signature.keyinfo.ext", "saml.multivalued.roles", + "saml.force.post.binding"); + + private static final Logger logger = LoggerFactory.getLogger(ClientNormalizationService.class); + private final Javers unOrderedJavers; + private final BaselineProvider baselineProvider; + private final JaversUtil javersUtil; + + public ClientNormalizationService(Javers unOrderedJavers, + BaselineProvider baselineProvider, + JaversUtil javersUtil) { + this.unOrderedJavers = unOrderedJavers; + this.baselineProvider = baselineProvider; + this.javersUtil = javersUtil; + } + + public List normalizeClients(RealmRepresentation exportedRealm, RealmRepresentation baselineRealm) { + var exportedOrEmpty = getNonNull(exportedRealm.getClients()); + var baselineOrEmpty = getNonNull(baselineRealm.getClients()); + var exportedClientMap = new HashMap(); + for (var exportedClient : exportedOrEmpty) { + exportedClientMap.put(exportedClient.getClientId(), exportedClient); + } + + var baselineClientMap = new HashMap(); + var clients = new ArrayList(); + for (var baselineRealmClient : baselineOrEmpty) { + var clientId = baselineRealmClient.getClientId(); + baselineClientMap.put(clientId, baselineRealmClient); + var exportedClient = exportedClientMap.get(clientId); + if (exportedClient == null) { + logger.warn("Default realm client '{}' was deleted in exported realm. It may be reintroduced during import!", clientId); + /* + * Here we need to define a configuration parameter: If we want the import *not* to reintroduce default clients that were + * deleted, we need to add *all* clients, not just default clients to the dump. Then during import, set the mode that + * makes clients fully managed, so that *only* clients that are in the dump end up in the realm + */ + continue; + } + if (clientChanged(exportedClient, baselineRealmClient)) { + // We know the client has changed in some way. Now, compare it to a default client to minimize it + clients.add(normalizeClient(exportedClient, exportedRealm.getKeycloakVersion(), exportedRealm)); + } + } + + // Now iterate over all the clients that are *not* default clients + for (Map.Entry e : exportedClientMap.entrySet()) { + if (!baselineClientMap.containsKey(e.getKey())) { + clients.add(normalizeClient(e.getValue(), exportedRealm.getKeycloakVersion(), exportedRealm)); + } + } + return clients; + } + + public ClientRepresentation normalizeClient(ClientRepresentation client, String keycloakVersion, RealmRepresentation exportedRealm) { + var clientId = client.getClientId(); + var baselineClient = baselineProvider.getClient(keycloakVersion, clientId); + var diff = unOrderedJavers.compare(baselineClient, client); + var normalizedClient = new ClientRepresentation(); + for (var change : diff.getChangesByType(PropertyChange.class)) { + javersUtil.applyChange(normalizedClient, change); + } + + // Always include protocol, even if it's the default "openid-connect" + normalizedClient.setProtocol(client.getProtocol()); + var mappers = client.getProtocolMappers(); + normalizedClient.setProtocolMappers(mappers); + if (mappers != null) { + for (var mapper : mappers) { + mapper.setId(null); + } + } + normalizedClient.setAuthorizationSettings(client.getAuthorizationSettings()); + normalizedClient.setClientId(clientId); + + // Older versions of keycloak include SAML attributes even in OIDC clients. Ignore these. + if (normalizedClient.getProtocol().equals("openid-connect") && normalizedClient.getAttributes() != null) { + normalizedClient.getAttributes().keySet().removeIf(SAML_ATTRIBUTES::contains); + } + + if (normalizedClient.getAuthenticationFlowBindingOverrides() != null) { + var overrides = new HashMap(); + var flows = exportedRealm.getAuthenticationFlows().stream() + .collect(Collectors.toMap(AuthenticationFlowRepresentation::getId, AuthenticationFlowRepresentation::getAlias)); + for (var entry : normalizedClient.getAuthenticationFlowBindingOverrides().entrySet()) { + var id = entry.getValue(); + overrides.put(entry.getKey(), flows.get(id)); + } + normalizedClient.setAuthenticationFlowBindingOverrides(overrides); + } + normalizedClient.setPublicClient(client.isPublicClient()); + return normalizedClient; + } + + public boolean clientChanged(ClientRepresentation exportedClient, ClientRepresentation baselineClient) { + var diff = unOrderedJavers.compare(baselineClient, exportedClient); + if (diff.hasChanges()) { + return true; + } + if (protocolMappersChanged(exportedClient.getProtocolMappers(), baselineClient.getProtocolMappers())) { + return true; + } + return authorizationSettingsChanged(exportedClient.getAuthorizationSettings(), baselineClient.getAuthorizationSettings()); + } + + public boolean protocolMappersChanged(List exportedMappers, List baselineMappers) { + // CompareCollections doesn't handle nulls gracefully + return unOrderedJavers.compareCollections(getNonNull(baselineMappers), getNonNull(exportedMappers), ProtocolMapperRepresentation.class) + .hasChanges(); + } + + public boolean authorizationSettingsChanged(ResourceServerRepresentation exportedSettings, ResourceServerRepresentation baselineSettings) { + return unOrderedJavers.compare(baselineSettings, exportedSettings).hasChanges(); + } + +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientPolicyNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientPolicyNormalizationService.java new file mode 100644 index 000000000..823e13257 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientPolicyNormalizationService.java @@ -0,0 +1,49 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2023 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.keycloak.representations.idm.ClientPoliciesRepresentation; +import org.keycloak.representations.idm.ClientProfilesRepresentation; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class ClientPolicyNormalizationService { + + public ClientPoliciesRepresentation normalizePolicies(ClientPoliciesRepresentation exportedPolicies, + ClientPoliciesRepresentation baselinePolicies) { + var policies = exportedPolicies.getPolicies(); + if (policies == null || policies.isEmpty()) { + return null; + } + return exportedPolicies; + } + + public ClientProfilesRepresentation normalizeProfiles(ClientProfilesRepresentation exportedProfiles, + ClientProfilesRepresentation baselineProfiles) { + var profiles = exportedProfiles.getProfiles(); + if (profiles == null || profiles.isEmpty()) { + return null; + } + return exportedProfiles; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientScopeNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientScopeNormalizationService.java new file mode 100644 index 000000000..3825beee2 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/ClientScopeNormalizationService.java @@ -0,0 +1,107 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.ClientScopeRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class ClientScopeNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(ClientScopeNormalizationService.class); + + private final Javers unOrderedJavers; + + public ClientScopeNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public List normalizeClientScopes(List exportedScopes, + List baselineScopes) { + var exportedOrEmpty = getNonNull(exportedScopes); + var baselineOrEmpty = getNonNull(baselineScopes); + + var exportedMap = exportedOrEmpty.stream().collect(Collectors.toMap(ClientScopeRepresentation::getName, + Function.identity())); + var baselineMap = baselineOrEmpty.stream().collect(Collectors.toMap(ClientScopeRepresentation::getName, + Function.identity())); + + var normalizedScopes = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var scopeName = entry.getKey(); + var baselineScope = entry.getValue(); + var exportedScope = exportedMap.remove(scopeName); + + if (exportedScope == null) { + logger.warn("Default realm clientScope '{}' was deleted in exported realm. It may be reintroduced during import!", scopeName); + continue; + } + + if (clientScopeChanged(exportedScope, baselineScope)) { + normalizedScopes.add(exportedScope); + } + } + normalizedScopes.addAll(exportedMap.values()); + + normalizeList(normalizedScopes); + return normalizedScopes.isEmpty() ? null : normalizedScopes; + } + + private static void normalizeList(ArrayList normalizedScopes) { + for (var scope : normalizedScopes) { + scope.setId(null); + if (scope.getProtocolMappers() != null) { + for (var mapper : scope.getProtocolMappers()) { + mapper.setId(null); + } + if (scope.getProtocolMappers().isEmpty()) { + scope.setProtocolMappers(null); + } + } + } + } + + public boolean clientScopeChanged(ClientScopeRepresentation exportedScope, ClientScopeRepresentation baselineScope) { + if (unOrderedJavers.compare(baselineScope, exportedScope).hasChanges()) { + return true; + } + + return protocolMappersChanged(exportedScope.getProtocolMappers(), baselineScope.getProtocolMappers()); + } + + public boolean protocolMappersChanged(List exportedMappers, List baselineMappers) { + return unOrderedJavers.compareCollections(getNonNull(baselineMappers), getNonNull(exportedMappers), + ProtocolMapperRepresentation.class).hasChanges(); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/ComponentNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/ComponentNormalizationService.java new file mode 100644 index 000000000..274fa709f --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/ComponentNormalizationService.java @@ -0,0 +1,90 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.common.util.MultivaluedHashMap; +import org.keycloak.representations.idm.ComponentExportRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class ComponentNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(ComponentNormalizationService.class); + + private final Javers unOrderedJavers; + + public ComponentNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public MultivaluedHashMap + normalizeComponents(MultivaluedHashMap exportedComponents, + MultivaluedHashMap baselineComponents) { + var exportedOrEmpty = getNonNull(exportedComponents); + var baselineOrEmpty = getNonNull(baselineComponents); + + var normalizedMap = new MultivaluedHashMap(); + for (var entry : baselineOrEmpty.entrySet()) { + var componentClass = entry.getKey(); + + var exportedList = exportedOrEmpty.remove(componentClass); + + if (exportedList == null) { + logger.warn("Default realm component '{}' was deleted in exported realm. It may be reintroduced during import!", componentClass); + continue; + } + var baselineList = entry.getValue(); + var normalizedList = normalizeList(exportedList, baselineList, componentClass); + normalizedMap.put(componentClass, normalizedList); + } + normalizedMap.putAll(exportedOrEmpty); + //var toRemove = new HashSet(); + for (var entry : normalizedMap.entrySet()) { + var componentList = entry.getValue(); + for (var component : componentList) { + normalizeEntry(component); + } + } + return new MultivaluedHashMap<>(); + } + + public List normalizeList(List exportedComponents, + List baselineComponents, + String componentClass) { + return List.of(); + } + + public void normalizeEntry(ComponentExportRepresentation component) { + component.setId(null); + if (component.getConfig() != null && component.getConfig().isEmpty()) { + component.setConfig(null); + } + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/GroupNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/GroupNormalizationService.java new file mode 100644 index 000000000..10cf28c6b --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/GroupNormalizationService.java @@ -0,0 +1,141 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.GroupRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class GroupNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(GroupNormalizationService.class); + + private final Javers unOrderedJavers; + private final AttributeNormalizationService attributeNormalizationService; + + public GroupNormalizationService(Javers unOrderedJavers, + AttributeNormalizationService attributeNormalizationService) { + this.unOrderedJavers = unOrderedJavers; + this.attributeNormalizationService = attributeNormalizationService; + } + + public List normalizeGroups(List exportedGroups, List baselineGroups) { + var exportedOrEmpty = getNonNull(exportedGroups); + var baselineOrEmpty = getNonNull(baselineGroups); + var exportedGroupsMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(GroupRepresentation::getPath, Function.identity())); + var baselineGroupsMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(GroupRepresentation::getPath, Function.identity())); + + var normalizedGroups = new ArrayList(); + for (var entry : baselineGroupsMap.entrySet()) { + var groupPath = entry.getKey(); + var exportedGroup = exportedGroupsMap.remove(groupPath); + if (exportedGroup == null) { + logger.warn("Default realm group '{}' was deleted in exported realm. It may be reintroduced during import", groupPath); + continue; + } + var baselineGroup = entry.getValue(); + var diff = unOrderedJavers.compare(baselineGroup, exportedGroup); + + if (diff.hasChanges() || subGroupsChanged(exportedGroup, baselineGroup) + || attributeNormalizationService.listAttributesChanged(exportedGroup.getAttributes(), baselineGroup.getAttributes()) + || attributeNormalizationService.listAttributesChanged(exportedGroup.getClientRoles(), baselineGroup.getClientRoles())) { + normalizedGroups.add(exportedGroup); + } + } + normalizedGroups.addAll(exportedGroupsMap.values()); + normalizeGroupList(normalizedGroups); + return normalizedGroups.isEmpty() ? null : normalizedGroups; + } + + public boolean subGroupsChanged(GroupRepresentation exportedGroup, GroupRepresentation baselineGroup) { + if (exportedGroup.getSubGroups() == null && baselineGroup.getSubGroups() != null) { + return true; + } + if (exportedGroup.getSubGroups() != null && baselineGroup.getSubGroups() == null) { + return true; + } + if (exportedGroup.getSubGroups() == null && baselineGroup.getSubGroups() == null) { + return false; + } + + Map exportedSubGroups = exportedGroup.getSubGroups().stream() + .collect(Collectors.toMap(GroupRepresentation::getPath, Function.identity())); + Map baselineSubGroups = baselineGroup.getSubGroups().stream() + .collect(Collectors.toMap(GroupRepresentation::getPath, Function.identity())); + + for (var entry : baselineSubGroups.entrySet()) { + var groupPath = entry.getKey(); + var exportedSubGroup = exportedSubGroups.remove(groupPath); + + if (exportedSubGroup == null) { + // There's a subgroup in the baseline that's gone in the export. This counts as a change. + return true; + } + var baselineSubGroup = entry.getValue(); + if (unOrderedJavers.compare(baselineSubGroup, exportedSubGroup).hasChanges()) { + return true; + } + if (subGroupsChanged(exportedSubGroup, baselineSubGroup)) { + return true; + } + } + + // There are subgroups in the export that are not in the baseline. This is a change. + return !exportedSubGroups.isEmpty(); + } + + public void normalizeGroupList(List groups) { + for (var group : groups) { + if (group.getAttributes() != null && group.getAttributes().isEmpty()) { + group.setAttributes(null); + } + if (group.getRealmRoles() != null && group.getRealmRoles().isEmpty()) { + group.setRealmRoles(null); + } + if (group.getClientRoles() != null && group.getClientRoles().isEmpty()) { + group.setClientRoles(null); + } + if (group.getSubGroups() != null) { + if (group.getSubGroups().isEmpty()) { + group.setSubGroups(null); + } else { + normalizeGroupList(group.getSubGroups()); + } + } + group.setId(null); + } + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/IdentityProviderNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/IdentityProviderNormalizationService.java new file mode 100644 index 000000000..a5d87cdcf --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/IdentityProviderNormalizationService.java @@ -0,0 +1,149 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class IdentityProviderNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(IdentityProviderNormalizationService.class); + + private final Javers unOrderedJavers; + + public IdentityProviderNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public List normalizeProviders(List exportedProviders, + List baselineProviders) { + var exportedOrEmpty = getNonNull(exportedProviders); + var baselineOrEmpty = getNonNull(baselineProviders); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(IdentityProviderRepresentation::getAlias, Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(IdentityProviderRepresentation::getAlias, Function.identity())); + + var normalizedProviders = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var alias = entry.getKey(); + var exportedProvider = exportedMap.remove(alias); + if (exportedProvider == null) { + logger.warn("Default realm identityProvider '{}' was deleted in exported realm. It may be reintroduced during import!", alias); + continue; + } + var baselineProvider = entry.getValue(); + + var diff = unOrderedJavers.compare(baselineProvider, exportedProvider); + if (diff.hasChanges()) { + normalizedProviders.add(exportedProvider); + } + } + normalizedProviders.addAll(exportedMap.values()); + for (var provider : normalizedProviders) { + provider.setInternalId(null); + if (provider.getConfig() != null && provider.getConfig().isEmpty()) { + provider.setConfig(null); + } + } + return normalizedProviders.isEmpty() ? null : normalizedProviders; + } + + public List normalizeMappers(List exportedMappers, + List baselineMappers) { + var exportedOrEmpty = getNonNull(exportedMappers); + var baselineOrEmpty = getNonNull(baselineMappers); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(m -> new MapperKey(m.getName(), m.getIdentityProviderAlias()), Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(m -> new MapperKey(m.getName(), m.getIdentityProviderAlias()), Function.identity())); + + var normalizedMappers = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var key = entry.getKey(); + var exportedMapper = exportedMap.remove(key); + if (exportedMapper == null) { + logger.warn("Default realm identityProviderMapper '{}' for idp '{}' was deleted in exported realm." + + "It may be reintroduced during import!", key.getName(), key.getIdentityProviderAlias()); + continue; + } + var baselineMapper = entry.getValue(); + + var diff = unOrderedJavers.compare(baselineMapper, exportedMapper); + if (diff.hasChanges()) { + normalizedMappers.add(exportedMapper); + } + } + normalizedMappers.addAll(exportedMap.values()); + for (var mapper : normalizedMappers) { + mapper.setId(null); + } + return normalizedMappers.isEmpty() ? null : normalizedMappers; + } + + private static class MapperKey { + private final String name; + private final String identityProviderAlias; + + public MapperKey(String name, String identityProviderAlias) { + this.name = name; + this.identityProviderAlias = identityProviderAlias; + } + + public String getName() { + return name; + } + + public String getIdentityProviderAlias() { + return identityProviderAlias; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MapperKey mapperKey = (MapperKey) o; + return Objects.equals(name, mapperKey.name) && Objects.equals(identityProviderAlias, mapperKey.identityProviderAlias); + } + + @Override + public int hashCode() { + return Objects.hash(name, identityProviderAlias); + } + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/ProtocolMapperNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/ProtocolMapperNormalizationService.java new file mode 100644 index 000000000..1a65f85b6 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/ProtocolMapperNormalizationService.java @@ -0,0 +1,82 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class ProtocolMapperNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(IdentityProviderNormalizationService.class); + + private final Javers unOrderedJavers; + + public ProtocolMapperNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public List normalizeProtocolMappers(List exportedMappers, + List baselineMappers) { + var exportedOrEmpty = getNonNull(exportedMappers); + var baselineOrEmpty = getNonNull(baselineMappers); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(ProtocolMapperRepresentation::getName, Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(ProtocolMapperRepresentation::getName, Function.identity())); + var normalizedMappers = new ArrayList(); + + for (var entry : baselineMap.entrySet()) { + var name = entry.getKey(); + var exportedMapper = exportedMap.remove(name); + if (exportedMapper == null) { + logger.warn("Default realm protocolMapper '{}' was deleted in exported realm. It may be reintroduced during import!", name); + continue; + } + + var baselineMapper = entry.getValue(); + if (unOrderedJavers.compare(baselineMapper, exportedMapper).hasChanges()) { + normalizedMappers.add(exportedMapper); + } + } + normalizedMappers.addAll(exportedMap.values()); + for (var mapper : normalizedMappers) { + mapper.setId(null); + if (mapper.getConfig() != null && mapper.getConfig().isEmpty()) { + mapper.setConfig(null); + } + } + return normalizedMappers.isEmpty() ? null : normalizedMappers; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/RealmNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/RealmNormalizationService.java new file mode 100644 index 000000000..cb9e1b16b --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/RealmNormalizationService.java @@ -0,0 +1,211 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import de.adorsys.keycloak.config.properties.NormalizationKeycloakConfigProperties; +import de.adorsys.keycloak.config.provider.BaselineProvider; +import de.adorsys.keycloak.config.util.JaversUtil; +import org.javers.core.Javers; +import org.javers.core.diff.changetype.PropertyChange; +import org.keycloak.representations.idm.RealmRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class RealmNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(RealmNormalizationService.class); + + private final NormalizationKeycloakConfigProperties keycloakConfigProperties; + private final Javers javers; + private final BaselineProvider baselineProvider; + private final ClientNormalizationService clientNormalizationService; + private final ScopeMappingNormalizationService scopeMappingNormalizationService; + private final ProtocolMapperNormalizationService protocolMapperNormalizationService; + private final ClientScopeNormalizationService clientScopeNormalizationService; + private final RoleNormalizationService roleNormalizationService; + private final AttributeNormalizationService attributeNormalizationService; + private final GroupNormalizationService groupNormalizationService; + private final AuthFlowNormalizationService authFlowNormalizationService; + private final IdentityProviderNormalizationService identityProviderNormalizationService; + private final RequiredActionNormalizationService requiredActionNormalizationService; + private final UserFederationNormalizationService userFederationNormalizationService; + private final ClientPolicyNormalizationService clientPolicyNormalizationService; + private final JaversUtil javersUtil; + + @Autowired + public RealmNormalizationService(NormalizationKeycloakConfigProperties keycloakConfigProperties, + Javers javers, + BaselineProvider baselineProvider, + ClientNormalizationService clientNormalizationService, + ScopeMappingNormalizationService scopeMappingNormalizationService, + ProtocolMapperNormalizationService protocolMapperNormalizationService, + ClientScopeNormalizationService clientScopeNormalizationService, + RoleNormalizationService roleNormalizationService, + AttributeNormalizationService attributeNormalizationService, + GroupNormalizationService groupNormalizationService, + AuthFlowNormalizationService authFlowNormalizationService, + IdentityProviderNormalizationService identityProviderNormalizationService, + RequiredActionNormalizationService requiredActionNormalizationService, + UserFederationNormalizationService userFederationNormalizationService, + ClientPolicyNormalizationService clientPolicyNormalizationService, + JaversUtil javersUtil) { + this.keycloakConfigProperties = keycloakConfigProperties; + this.javers = javers; + this.baselineProvider = baselineProvider; + this.clientNormalizationService = clientNormalizationService; + this.scopeMappingNormalizationService = scopeMappingNormalizationService; + this.protocolMapperNormalizationService = protocolMapperNormalizationService; + this.clientScopeNormalizationService = clientScopeNormalizationService; + this.roleNormalizationService = roleNormalizationService; + this.attributeNormalizationService = attributeNormalizationService; + this.groupNormalizationService = groupNormalizationService; + this.authFlowNormalizationService = authFlowNormalizationService; + this.identityProviderNormalizationService = identityProviderNormalizationService; + this.requiredActionNormalizationService = requiredActionNormalizationService; + this.userFederationNormalizationService = userFederationNormalizationService; + this.clientPolicyNormalizationService = clientPolicyNormalizationService; + this.javersUtil = javersUtil; + + // TODO allow extra "default" values to be ignored? + + // TODO Ignore clients by regex + } + + public RealmRepresentation normalizeRealm(RealmRepresentation exportedRealm) { + var keycloakConfigVersion = keycloakConfigProperties.getVersion(); + var exportVersion = exportedRealm.getKeycloakVersion(); + if (!exportVersion.equals(keycloakConfigVersion)) { + logger.warn("Keycloak-Config-CLI keycloak version {} and export keycloak version {} are not equal." + + " This may cause problems if the API changed." + + " Please compile keycloak-config-cli with a matching keycloak version!", + keycloakConfigVersion, exportVersion); + } + var exportedRealmRealm = exportedRealm.getRealm(); + logger.info("Exporting realm {}", exportedRealmRealm); + var baselineRealm = baselineProvider.getRealm(exportVersion, exportedRealmRealm); + + /* + * Trick javers into thinking this is the "same" object, by setting the ID on the reference realm + * to the ID of the current realm. That way we only get actual changes, not a full list of changes + * including the "object removed" and "object added" changes + */ + baselineRealm.setRealm(exportedRealm.getRealm()); + var minimizedRealm = new RealmRepresentation(); + + handleBaseRealm(exportedRealm, baselineRealm, minimizedRealm); + + var clients = clientNormalizationService.normalizeClients(exportedRealm, baselineRealm); + if (!clients.isEmpty()) { + minimizedRealm.setClients(clients); + } + + // No setter for some reason... + var minimizedScopeMappings = scopeMappingNormalizationService.normalizeScopeMappings(exportedRealm, baselineRealm); + if (!minimizedScopeMappings.isEmpty()) { + var scopeMappings = minimizedRealm.getScopeMappings(); + if (scopeMappings == null) { + minimizedRealm.clientScopeMapping("dummy"); + scopeMappings = minimizedRealm.getScopeMappings(); + scopeMappings.clear(); + } + scopeMappings.addAll(minimizedScopeMappings); + } + + var clientScopeMappings = scopeMappingNormalizationService.normalizeClientScopeMappings(exportedRealm, baselineRealm); + if (!clientScopeMappings.isEmpty()) { + minimizedRealm.setClientScopeMappings(clientScopeMappings); + } + + minimizedRealm.setAttributes(attributeNormalizationService.normalizeStringAttributes(exportedRealm.getAttributes(), + baselineRealm.getAttributes())); + + minimizedRealm.setProtocolMappers(protocolMapperNormalizationService.normalizeProtocolMappers(exportedRealm.getProtocolMappers(), + baselineRealm.getProtocolMappers())); + + minimizedRealm.setClientScopes(clientScopeNormalizationService.normalizeClientScopes(exportedRealm.getClientScopes(), + baselineRealm.getClientScopes())); + + minimizedRealm.setRoles(roleNormalizationService.normalizeRoles(exportedRealm.getRoles(), baselineRealm.getRoles())); + + minimizedRealm.setGroups(groupNormalizationService.normalizeGroups(exportedRealm.getGroups(), baselineRealm.getGroups())); + + var authFlows = authFlowNormalizationService.normalizeAuthFlows(exportedRealm.getAuthenticationFlows(), + baselineRealm.getAuthenticationFlows()); + minimizedRealm.setAuthenticationFlows(authFlows); + minimizedRealm.setAuthenticatorConfig(authFlowNormalizationService.normalizeAuthConfig(exportedRealm.getAuthenticatorConfig(), authFlows)); + + minimizedRealm.setIdentityProviders(identityProviderNormalizationService.normalizeProviders(exportedRealm.getIdentityProviders(), + baselineRealm.getIdentityProviders())); + minimizedRealm.setIdentityProviderMappers(identityProviderNormalizationService.normalizeMappers(exportedRealm.getIdentityProviderMappers(), + baselineRealm.getIdentityProviderMappers())); + + minimizedRealm.setRequiredActions(requiredActionNormalizationService.normalizeRequiredActions(exportedRealm.getRequiredActions(), + baselineRealm.getRequiredActions())); + minimizedRealm.setUserFederationProviders(userFederationNormalizationService.normalizeProviders(exportedRealm.getUserFederationProviders(), + baselineRealm.getUserFederationProviders())); + minimizedRealm.setUserFederationMappers(userFederationNormalizationService.normalizeMappers(exportedRealm.getUserFederationMappers(), + baselineRealm.getUserFederationMappers())); + + minimizedRealm.setParsedClientPolicies(clientPolicyNormalizationService.normalizePolicies(exportedRealm.getParsedClientPolicies(), + baselineRealm.getParsedClientPolicies())); + minimizedRealm.setParsedClientProfiles(clientPolicyNormalizationService.normalizeProfiles(exportedRealm.getParsedClientProfiles(), + baselineRealm.getParsedClientProfiles())); + return minimizedRealm; + } + + private void handleBaseRealm(RealmRepresentation exportedRealm, RealmRepresentation baselineRealm, RealmRepresentation minimizedRealm) { + var diff = javers.compare(baselineRealm, exportedRealm); + for (var change : diff.getChangesByType(PropertyChange.class)) { + javersUtil.applyChange(minimizedRealm, change); + } + + // Now that Javers is done, clean up a bit afterwards. We always need to set the realm and enabled fields + minimizedRealm.setRealm(exportedRealm.getRealm()); + minimizedRealm.setEnabled(exportedRealm.isEnabled()); + + // If the realm ID diverges from the name, include it in the dump, otherwise remove it + if (Objects.equals(exportedRealm.getRealm(), exportedRealm.getId())) { + minimizedRealm.setId(null); + } else { + minimizedRealm.setId(exportedRealm.getId()); + } + } + + + public static Map getNonNull(Map in) { + return in == null ? new HashMap<>() : in; + } + + public static List getNonNull(List in) { + return in == null ? new ArrayList<>() : in; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/RequiredActionNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/RequiredActionNormalizationService.java new file mode 100644 index 000000000..361357d0d --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/RequiredActionNormalizationService.java @@ -0,0 +1,77 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.RequiredActionProviderRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class RequiredActionNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(RequiredActionNormalizationService.class); + + private final Javers javers; + + public RequiredActionNormalizationService(Javers javers) { + this.javers = javers; + } + + public List normalizeRequiredActions(List exportedActions, + List baselineActions) { + var exportedOrEmpty = getNonNull(exportedActions); + var baselineOrEmpty = getNonNull(baselineActions); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(RequiredActionProviderRepresentation::getAlias, Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(RequiredActionProviderRepresentation::getAlias, Function.identity())); + + var normalizedActions = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var alias = entry.getKey(); + var exportedAction = exportedMap.remove(alias); + if (exportedAction == null) { + logger.warn("Default realm requiredAction '{}' was deleted in exported realm. It may be reintroduced during import", alias); + continue; + } + var baselineAction = entry.getValue(); + + var diff = javers.compare(baselineAction, exportedAction); + if (diff.hasChanges()) { + normalizedActions.add(exportedAction); + } + } + normalizedActions.addAll(exportedMap.values()); + return normalizedActions.isEmpty() ? null : normalizedActions; + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/RoleNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/RoleNormalizationService.java new file mode 100644 index 000000000..a4209b8a3 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/RoleNormalizationService.java @@ -0,0 +1,161 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.RoleRepresentation; +import org.keycloak.representations.idm.RolesRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class RoleNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(RoleNormalizationService.class); + + private final Javers unOrderedJavers; + private final AttributeNormalizationService attributeNormalizationService; + + @Autowired + public RoleNormalizationService(Javers unOrderedJavers, AttributeNormalizationService attributeNormalizationService) { + this.unOrderedJavers = unOrderedJavers; + this.attributeNormalizationService = attributeNormalizationService; + } + + public RolesRepresentation normalizeRoles(RolesRepresentation exportedRoles, RolesRepresentation baselineRoles) { + var exportedOrEmpty = exportedRoles == null ? new RolesRepresentation() : exportedRoles; + var baselineOrEmpty = baselineRoles == null ? new RolesRepresentation() : baselineRoles; + var clientRoles = normalizeClientRoles(exportedOrEmpty.getClient(), baselineOrEmpty.getClient()); + var realmRoles = normalizeRealmRoles(exportedOrEmpty.getRealm(), baselineOrEmpty.getRealm()); + var normalizedRoles = new RolesRepresentation(); + if (!clientRoles.isEmpty()) { + normalizedRoles.setClient(clientRoles); + } + if (!realmRoles.isEmpty()) { + normalizedRoles.setRealm(realmRoles); + } + + // avoid generating an empty roles element + if (normalizedRoles.getRealm() == null || (normalizedRoles.getRealm().isEmpty() && normalizedRoles.getClient().isEmpty())) { + return null; + } + + return normalizedRoles; + } + + public List normalizeRealmRoles(List exportedRoles, List baselineRoles) { + return normalizeRoleList(exportedRoles, baselineRoles, null); + } + + public Map> normalizeClientRoles(Map> exportedRoles, + Map> baselineRoles) { + var exportedOrEmpty = getNonNull(exportedRoles); + var baselineOrEmpty = getNonNull(baselineRoles); + + var normalizedRoles = new HashMap>(); + for (var entry : baselineOrEmpty.entrySet()) { + var clientId = entry.getKey(); + var baselineClientRoles = entry.getValue(); + var exportedClientRoles = exportedOrEmpty.remove(clientId); + exportedClientRoles = getNonNull(exportedClientRoles); + + var normalizedClientRoles = normalizeRoleList(exportedClientRoles, baselineClientRoles, clientId); + if (!normalizedClientRoles.isEmpty()) { + normalizedRoles.put(clientId, normalizedClientRoles); + } + } + + for (var entry : exportedOrEmpty.entrySet()) { + var clientId = entry.getKey(); + var roles = entry.getValue(); + + if (!roles.isEmpty()) { + normalizedRoles.put(clientId, normalizeList(roles)); + } + } + return normalizedRoles; + } + + public List normalizeRoleList(List exportedRoles, + List baselineRoles, String clientId) { + var exportedOrEmpty = getNonNull(exportedRoles); + var baselineOrEmpty = getNonNull(baselineRoles); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(RoleRepresentation::getName, Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(RoleRepresentation::getName, Function.identity())); + var normalizedRoles = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var roleName = entry.getKey(); + var exportedRole = exportedMap.remove(roleName); + if (exportedRole == null) { + if (clientId == null) { + logger.warn("Default realm role '{}' was deleted in exported realm. It may be reintroduced during import!", roleName); + } else { + logger.warn("Default realm client-role '{}' for client '{}' was deleted in the exported realm. " + + "It may be reintroduced during import!", roleName, clientId); + } + continue; + } + + var baselineRole = entry.getValue(); + + var diff = unOrderedJavers.compare(baselineRole, exportedRole); + + if (diff.hasChanges() + || compositesChanged(exportedRole.getComposites(), baselineRole.getComposites()) + || attributeNormalizationService.listAttributesChanged(exportedRole.getAttributes(), baselineRole.getAttributes())) { + normalizedRoles.add(exportedRole); + } + } + normalizedRoles.addAll(exportedMap.values()); + return normalizeList(normalizedRoles); + } + + public List normalizeList(List roles) { + for (var role : roles) { + role.setId(null); + if (role.getAttributes() != null && role.getAttributes().isEmpty()) { + role.setAttributes(null); + } + } + return roles; + } + + public boolean compositesChanged(RoleRepresentation.Composites exportedComposites, RoleRepresentation.Composites baselineComposites) { + return unOrderedJavers.compare(baselineComposites, exportedComposites) + .hasChanges(); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/ScopeMappingNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/ScopeMappingNormalizationService.java new file mode 100644 index 000000000..f713a2351 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/ScopeMappingNormalizationService.java @@ -0,0 +1,117 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.ScopeMappingRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class ScopeMappingNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(ScopeMappingNormalizationService.class); + + private final Javers javers; + + public ScopeMappingNormalizationService(Javers javers) { + this.javers = javers; + } + + public List normalizeScopeMappings(RealmRepresentation exportedRealm, RealmRepresentation baselineRealm) { + /* + * TODO: are the mappings in scopeMappings always clientScope/role? If not, this breaks + */ + // First handle the "default" scopeMappings present in the + var exportedMappingsMap = new HashMap(); + for (var exportedMapping : exportedRealm.getScopeMappings()) { + exportedMappingsMap.put(exportedMapping.getClientScope(), exportedMapping); + } + + var baselineMappingsMap = new HashMap(); + + var mappings = new ArrayList(); + for (var baselineRealmMapping : baselineRealm.getScopeMappings()) { + var clientScope = baselineRealmMapping.getClientScope(); + baselineMappingsMap.put(clientScope, baselineRealmMapping); + var exportedMapping = exportedMappingsMap.get(clientScope); + if (exportedMapping == null) { + logger.warn("Default realm scopeMapping '{}' was deleted in exported realm. It may be reintroduced during import!", clientScope); + continue; + } + // If the exported scopeMapping is different from the one that is present in the baseline realm, export it in the yml + if (scopeMappingChanged(exportedMapping, baselineRealmMapping)) { + mappings.add(exportedMapping); + } + } + + for (Map.Entry e : exportedMappingsMap.entrySet()) { + var clientScope = e.getKey(); + if (!baselineMappingsMap.containsKey(clientScope)) { + mappings.add(e.getValue()); + } + } + return mappings; + } + + public Map> normalizeClientScopeMappings(RealmRepresentation exportedRealm, + RealmRepresentation baselineRealm) { + var baselineOrEmpty = getNonNull(baselineRealm.getClientScopeMappings()); + var exportedOrEmpty = getNonNull(exportedRealm.getClientScopeMappings()); + + var mappings = new HashMap>(); + for (var e : baselineOrEmpty.entrySet()) { + var key = e.getKey(); + if (!exportedOrEmpty.containsKey(key)) { + logger.warn("Default realm clientScopeMapping '{}' was deleted in exported realm. It may be reintroduced during import!", key); + continue; + } + var scopeMappings = exportedOrEmpty.get(key); + if (javers.compareCollections(e.getValue(), scopeMappings, ScopeMappingRepresentation.class).hasChanges()) { + mappings.put(key, scopeMappings); + } + } + + for (var e : exportedOrEmpty.entrySet()) { + var key = e.getKey(); + if (!baselineOrEmpty.containsKey(key)) { + mappings.put(key, e.getValue()); + } + } + return mappings; + } + + public boolean scopeMappingChanged(ScopeMappingRepresentation exportedMapping, ScopeMappingRepresentation baselineRealmMapping) { + return javers.compare(baselineRealmMapping, exportedMapping).hasChanges(); + } + +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/normalize/UserFederationNormalizationService.java b/src/main/java/de/adorsys/keycloak/config/service/normalize/UserFederationNormalizationService.java new file mode 100644 index 000000000..2821b7b39 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/normalize/UserFederationNormalizationService.java @@ -0,0 +1,154 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2023 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.service.normalize; + +import org.javers.core.Javers; +import org.keycloak.representations.idm.UserFederationMapperRepresentation; +import org.keycloak.representations.idm.UserFederationProviderRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static de.adorsys.keycloak.config.service.normalize.RealmNormalizationService.getNonNull; + +@Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class UserFederationNormalizationService { + + private static final Logger logger = LoggerFactory.getLogger(UserFederationNormalizationService.class); + + private final Javers unOrderedJavers; + + @Autowired + public UserFederationNormalizationService(Javers unOrderedJavers) { + this.unOrderedJavers = unOrderedJavers; + } + + public List normalizeProviders(List exportedProviders, + List baselineProviders) { + var exportedOrEmpty = getNonNull(exportedProviders); + var baselineOrEmpty = getNonNull(baselineProviders); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(UserFederationProviderRepresentation::getDisplayName, Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(UserFederationProviderRepresentation::getDisplayName, Function.identity())); + + var normalizedProviders = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var displayName = entry.getKey(); + var exportedProvider = exportedMap.remove(displayName); + + if (exportedProvider == null) { + logger.warn("Default realm UserFederationProvider '{}' was deleted in exported realm. " + + "It may be reintroduced during import!", displayName); + continue; + } + + var baselineProvider = entry.getValue(); + if (unOrderedJavers.compare(baselineProvider, exportedProvider).hasChanges()) { + normalizedProviders.add(exportedProvider); + } + } + normalizedProviders.addAll(exportedMap.values()); + for (var provider : normalizedProviders) { + provider.setId(null); + if (provider.getConfig() != null && provider.getConfig().isEmpty()) { + provider.setConfig(null); + } + } + return normalizedProviders.isEmpty() ? null : normalizedProviders; + } + + public List normalizeMappers(List exportedMappers, + List baselineMappers) { + var exportedOrEmpty = getNonNull(exportedMappers); + var baselineOrEmpty = getNonNull(baselineMappers); + + var exportedMap = exportedOrEmpty.stream() + .collect(Collectors.toMap(m -> new MapperKey(m.getName(), m.getFederationProviderDisplayName()), Function.identity())); + var baselineMap = baselineOrEmpty.stream() + .collect(Collectors.toMap(m -> new MapperKey(m.getName(), m.getFederationProviderDisplayName()), Function.identity())); + + var normalizedMappers = new ArrayList(); + for (var entry : baselineMap.entrySet()) { + var key = entry.getKey(); + var exportedMapper = exportedMap.remove(key); + if (exportedMapper == null) { + logger.warn("Default realm UserFederationMapper '{}' for federation '{}' was deleted in exported realm. " + + "It may be reintroduced during import!", key.getName(), key.getFederationDisplayName()); + } + + var baselineMapper = entry.getValue(); + if (unOrderedJavers.compare(baselineMapper, exportedMapper).hasChanges()) { + normalizedMappers.add(exportedMapper); + } + } + normalizedMappers.addAll(exportedMap.values()); + for (var mapper : normalizedMappers) { + mapper.setId(null); + if (mapper.getConfig() != null && mapper.getConfig().isEmpty()) { + mapper.setConfig(null); + } + } + return normalizedMappers.isEmpty() ? null : normalizedMappers; + } + + private static class MapperKey { + private final String name; + private final String federationDisplayName; + + public MapperKey(String name, String federationDisplayName) { + this.name = name; + this.federationDisplayName = federationDisplayName; + } + + public String getName() { + return name; + } + + public String getFederationDisplayName() { + return federationDisplayName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UserFederationNormalizationService.MapperKey mapperKey = (UserFederationNormalizationService.MapperKey) o; + return Objects.equals(name, mapperKey.name) && Objects.equals(federationDisplayName, mapperKey.federationDisplayName); + } + + @Override + public int hashCode() { + return Objects.hash(name, federationDisplayName); + } + } + +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientCompositeImport.java b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientCompositeImport.java index 742a51ba8..488b8b9a4 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientCompositeImport.java +++ b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientCompositeImport.java @@ -26,12 +26,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; @Service("clientRoleClientCompositeImport") +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientCompositeImport { private static final Logger logger = LoggerFactory.getLogger(ClientCompositeImport.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientRoleCompositeImportService.java b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientRoleCompositeImportService.java index 2130abc0c..05b56fa43 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientRoleCompositeImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/ClientRoleCompositeImportService.java @@ -22,6 +22,7 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -32,6 +33,7 @@ * Implements the update mechanism for role composites of client-level roles */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientRoleCompositeImportService { private final RealmCompositeImport realmCompositeImport; diff --git a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/RealmCompositeImport.java b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/RealmCompositeImport.java index 1fe734179..126fd06eb 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/RealmCompositeImport.java +++ b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/client/RealmCompositeImport.java @@ -25,6 +25,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.Objects; @@ -32,6 +33,7 @@ import java.util.stream.Collectors; @Service("clientRoleRealmCompositeImport") +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RealmCompositeImport { private static final Logger logger = LoggerFactory.getLogger(RealmCompositeImport.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/ClientCompositeImport.java b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/ClientCompositeImport.java index ccfdf78c2..b469ec973 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/ClientCompositeImport.java +++ b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/ClientCompositeImport.java @@ -25,12 +25,14 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; @Service("realmRoleClientCompositeImport") +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class ClientCompositeImport { private static final Logger logger = LoggerFactory.getLogger(ClientCompositeImport.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmCompositeImport.java b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmCompositeImport.java index e7eb4f7ac..1cb9aa31d 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmCompositeImport.java +++ b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmCompositeImport.java @@ -25,6 +25,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.Objects; @@ -32,6 +33,7 @@ import java.util.stream.Collectors; @Service("realmRoleRealmCompositeImport") +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RealmCompositeImport { private static final Logger logger = LoggerFactory.getLogger(RealmCompositeImport.class); diff --git a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmRoleCompositeImportService.java b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmRoleCompositeImportService.java index 5292af18c..b3d484e86 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmRoleCompositeImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/rolecomposites/realm/RealmRoleCompositeImportService.java @@ -22,6 +22,7 @@ import org.keycloak.representations.idm.RoleRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.List; @@ -31,6 +32,7 @@ * Implements the update mechanism for role composites of realm-level roles */ @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class RealmRoleCompositeImportService { private final RealmCompositeImport realmCompositeImport; diff --git a/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java b/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java index 7cecd6d78..8913c53a7 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java @@ -29,6 +29,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -36,6 +37,7 @@ import java.util.Map; @Service +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class StateService { private static final Logger logger = LoggerFactory.getLogger(StateService.class); diff --git a/src/main/java/de/adorsys/keycloak/config/util/JaversUtil.java b/src/main/java/de/adorsys/keycloak/config/util/JaversUtil.java new file mode 100644 index 000000000..6ec32867c --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/util/JaversUtil.java @@ -0,0 +1,42 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.util; + +import de.adorsys.keycloak.config.exception.NormalizationException; +import org.javers.core.diff.changetype.PropertyChange; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class JaversUtil { + + public void applyChange(Object object, PropertyChange change) { + try { + var field = object.getClass().getDeclaredField(change.getPropertyName()); + field.setAccessible(true); + field.set(object, change.getRight()); + } catch (NoSuchFieldException | IllegalAccessException ex) { + throw new NormalizationException(String.format("Failed to set property %s on object of type %s", + change.getPropertyName(), object.getClass().getName()), ex); + } + } +} diff --git a/src/main/resources/application-normalize-dev.properties b/src/main/resources/application-normalize-dev.properties new file mode 100644 index 000000000..ada43bd0e --- /dev/null +++ b/src/main/resources/application-normalize-dev.properties @@ -0,0 +1,6 @@ +spring.output.ansi.enabled=ALWAYS +spring.config.import=classpath:application-debug.properties + +run.operation=NORMALIZE +normalization.files.input-locations=./exports/in/*.json +normalization.files.output-directory=./exports/out diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 25641213d..cae13948a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,6 +6,8 @@ spring.main.lazy-initialization=true spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration keycloak.version=@keycloak.version@ +normalize.version=@keycloak.version@ + keycloak.login-realm=master keycloak.user=admin keycloak.client-secret= diff --git a/src/main/resources/baseline/19.0.3/client/client.json b/src/main/resources/baseline/19.0.3/client/client.json new file mode 100644 index 000000000..858b1115b --- /dev/null +++ b/src/main/resources/baseline/19.0.3/client/client.json @@ -0,0 +1,45 @@ +{ + "id": "caa6606a-6056-475c-af05-8b0365bb8164", + "clientId": "reference-client", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "q0t682YLCCk2qd5dntjtcniGozLXIZ7h", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "client.secret.creation.time": "1667920370" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ], + "access": { + "view": true, + "configure": true, + "manage": true + } +} diff --git a/src/main/resources/baseline/19.0.3/realm/realm.json b/src/main/resources/baseline/19.0.3/realm/realm.json new file mode 100644 index 000000000..bf14005cb --- /dev/null +++ b/src/main/resources/baseline/19.0.3/realm/realm.json @@ -0,0 +1,2176 @@ +{ + "id": "REALM_NAME_PLACEHOLDER", + "realm": "REALM_NAME_PLACEHOLDER", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "0825e37b-b5bb-413d-9c1c-23457f17cb66", + "name": "default-roles-REALM_NAME_PLACEHOLDER", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "REALM_NAME_PLACEHOLDER", + "attributes": {} + }, + { + "id": "08b30ae4-52ba-45a9-b723-07e6ac57ae2f", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "REALM_NAME_PLACEHOLDER", + "attributes": {} + }, + { + "id": "372ddfc2-cd6e-4ca3-a30f-d39cb92ac12d", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "REALM_NAME_PLACEHOLDER", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "caf6ae68-6a16-4dfa-9a71-1149ceb8f79c", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "913aeddb-8be9-4060-86c7-30cf0fa892ee", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "15ee649c-ef5f-4fe8-a6c1-67a9db14b0c5", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "5d56f881-d3ff-49ad-929c-214afd641f8f", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "0ba58546-8487-4508-b81f-0735432accf2", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "f6f1b3c0-5d29-41b4-b2ec-cfab60e28a3b", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "2c6ddc11-206e-4e82-b894-9fca7cc85866", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "f9917916-7aca-413b-b7bc-452d3fca7a48", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "ad1d551b-3f03-445d-8ac0-51b1196413f0", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-groups", + "query-users" + ] + } + }, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "f645cca6-9d25-40f0-8ce9-d988a04d9bec", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "ce56402a-8925-4750-9269-6b035cfa334f", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "1e70f63f-0883-4452-bb1b-f179bf3c8c30", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "5cef1f90-8af8-4445-b6a3-05d6eb60c46c", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "e87e4aa8-8c15-44ba-9622-eec4eeae1997", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "baa31234-e4ed-4821-a696-6ccd686b5e1f", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "0d7127a0-cd7b-478c-9156-629fc321bca4", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "99d07b51-633c-4d25-9dc1-f779a219c246", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "manage-users", + "manage-identity-providers", + "view-clients", + "query-clients", + "view-events", + "query-users", + "view-realm", + "manage-events", + "view-users", + "create-client", + "manage-authorization", + "impersonation", + "manage-realm", + "view-identity-providers", + "query-groups", + "query-realms", + "manage-clients", + "view-authorization" + ] + } + }, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "118c289f-0b71-4edf-ac2a-7016cc0c674d", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + }, + { + "id": "30f43104-6914-4e4f-9f6d-219daf2f7991", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "631f9fd2-7539-4190-8983-0e94614c5b73", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "6045a69a-aec3-4a11-b4c3-3cae53f7a914", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "6eed48a3-64bd-48ed-ac7c-607f8e724258", + "attributes": {} + } + ], + "account": [ + { + "id": "4e27eb76-06ea-4547-ab5d-de8f9c745597", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + }, + { + "id": "60ae83a6-6ed1-4b4f-81cc-701b9a95ceb9", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + }, + { + "id": "f5f244ba-53de-45d7-9774-d4c915cd4ccb", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + }, + { + "id": "2abb2ef2-3e4c-43d5-9ab7-b096e19f3a56", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + }, + { + "id": "8eb01f07-3771-4b28-ab78-6f216079b508", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + }, + { + "id": "23954dae-8150-4183-8733-bce1349fb0ec", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + }, + { + "id": "734d080d-1f67-48e9-942f-9233f6eca901", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "0825e37b-b5bb-413d-9c1c-23457f17cb66", + "name": "default-roles-REALM_NAME_PLACEHOLDER", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "REALM_NAME_PLACEHOLDER" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "6c7757f2-9ed7-4609-8e41-f4316ca8d31e", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/REALM_NAME_PLACEHOLDER/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "fe6ddaaf-3a90-4942-ae6a-1f170c87fc3b", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/REALM_NAME_PLACEHOLDER/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "9f385a11-7b42-4f92-ac9b-7d286590a392", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "61ecc83e-d3f3-4b4f-a821-845094b3d9d4", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "6eed48a3-64bd-48ed-ac7c-607f8e724258", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "631f9fd2-7539-4190-8983-0e94614c5b73", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "05f3367b-492b-40e1-ba0c-f000aa3ad0ef", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/REALM_NAME_PLACEHOLDER/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/REALM_NAME_PLACEHOLDER/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "9d1f5814-fa63-4c36-ae10-747d30f47c69", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "23fc5623-9366-478f-9924-801d71f32489", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "31541a2f-1c88-43d9-96fe-9f9efbd096d4", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "1859a4f3-d051-4800-963f-45b624cccd57", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "a7777bff-a046-4fe3-a5a9-a520d79865ec", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "7d011629-d7f1-45ad-a09b-b4decb3d47ed", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "22a74f8c-4493-4a1a-bf97-f51466e336b3", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "7fb8529d-cb6f-4f31-b4c3-f6be6f74b47d", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "5bd8bfba-d8a3-4792-aaec-5f0513397193", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "89146d36-28d5-4750-933e-75014b203dcf", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "01025c61-c655-463d-967d-a45e88368472", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "ad80bcc7-66d4-44c0-b34e-65822a57359a", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "73346462-e569-4679-a57d-fe623bdc5a95", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "3842db0a-837f-4564-9e48-07c87f5d3258", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "f79aab58-4d4a-40ee-b879-a586ff956f12", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "ccb6bedc-b921-4c83-abe6-13de8c0e9795", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "19ae8192-0189-4644-a362-d08a0bce5680", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "a0d6d0c2-afd3-4b29-a99f-ff3002866519", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "1dcbfe97-e4ab-4df7-8517-4eaaa26ea410", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "8448e164-b72e-406e-b14b-ae5d1e72393a", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "c573ae92-f94a-494e-9403-f875d22d3e8d", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "09f992cc-2d64-4d4d-88ca-59a1b63325e9", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "04658d90-dc3d-4865-ac52-6f16570fcd76", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "de199ca1-e720-419f-aeee-e112568f5cff", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "08daf912-8959-4ba5-9c38-ffcd395d6487", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "d76e56a2-6237-46d5-a56b-0ecd1f979e85", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "6bc40007-ab16-48f6-ae81-a66a9062ad5c", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "0385dbe8-587c-49ab-a317-a15b5b52d456", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "28946b3e-0eab-44a5-8eee-d42088072306", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "e61c48dc-d083-4029-92d1-3c7a6f3d8bb9", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "62545d7c-ef2e-48a6-bff8-e2e9a2b16c3d", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "f1c75501-26b2-4d94-82aa-851e4fa3dd7c", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "046a0b0d-5256-48fe-9b8f-b5193d87ebdd", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + } + ] + }, + { + "id": "d807e61e-3661-44ff-a8cd-285458e6f763", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "fede614b-c46e-484c-8dba-9590cd0205fe", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "c8a4b7a9-c8ba-412b-a17d-e90a3c6393fd", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "de4bafae-e88c-4c2f-9001-311f5c141633", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "9aa11aac-4178-435b-83b3-2d85508e34bd", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "808ef7c4-b5d1-491c-ade0-559f38287e68", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "2a0ad1a6-d6f9-43cb-8ec1-8913a23339d7", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "oidc-address-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-user-property-mapper" + ] + } + }, + { + "id": "3695208c-32af-497b-9af9-5de878749899", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "b7317013-6157-4099-a1ee-194df4808b2d", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "2464d485-980d-447a-94e2-34cf96aad1f1", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "6460fb5a-bbb9-400b-aba7-85cbe8666341", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "c2093410-4c63-4436-9294-535c492912dc", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper" + ] + } + }, + { + "id": "f9ef3de5-1ad1-4c9c-92bd-62a070e13ba2", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "d75363d0-aed5-4fea-a97f-d0c1adb4fa63", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": [ + "ea50f128-6340-4f3e-8050-1e79ba559121" + ], + "secret": [ + "QYJipEnEXtsqk2OqtX1oyyQrANj03UWaGGf1p4yD28-x4MMOSxXVpEVTwZZvpgJeB-4L2lztTaJxVhANSO1lDQ" + ], + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + }, + { + "id": "594b0771-b860-4aa8-8a81-4b29ee5ac384", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEAsZSMHIVGaorVvBfVYzTAHzXO7/ilxcjty/hayFAB3C1CkEnKeYIs2hUv8s3DFrG26GBFRWI+HVX8yCCuwksDkF4kB6ZxpNV/NCwt4+Hv1Fr/A58eVHkriXajlOE9LUkvrSd04bGGD+SplAgCweQzVcHF5Iy4bvsIJ8ow5WKJ7dGtJlnU2ddBEdja2KhlFWBdqn2YCdvpuLGEYNGr5/ANBM6evcv/bU3tVdq64TPSC13kw/QicKzAU6H+4k8reIAgaEhtudqb6sWI9G0JiSPtb98psTZMFjoGb9yphOFsoSmljA3Ozp2wDVltV/zyk8Aw7J2I8EOCdjcX8BdkkQc6oQIDAQABAoIBABEdhJ2RGNbW97+vumDb6jJ34LCPUgbslULF9pX85BkBAbvfaNTqP4FrblokC8wJp9vgv3xu+hagvYLaZ42RZlAJSsaz+5sL+r0gDvI6Sf+5H4ANW4J/xTr0BNMqHFfbiG1Tcrf4ALhSbSe31/AxGuOGkBi1mWcU6dXP7oOFSk7x79FVmirB0bKGGwd2TNbrmtBSiDU33vUPxwGnDSsmw8TVHyjISiM0BfvVkS9RrBGqEnNm0iKccukRgengrqCK8D4fq65YPrQQQ9o9I50eU0qHoCiVJyNC2+MBpiOniShLO8jyiLAuhDKDfoKis5C6Hqm1yyf2PzwB1rIjV5XVf2ECgYEA6JiWMHHKfyR3QNvGjRp3Jfz/WQvLGXZCwVDowhlNRtfvGC56tEC+QAWxM/4l12u1NMyYSDeF44tYpzq0dGtVkTWTzQKNczTkGhValNMgFEUa8pwumBVVfrfLllA0VGrMW6fEAr8ta2gFODOWoViLSD0s0Jmu6CpdKSUzafcnMjkCgYEAw3LQ2sLgGL8LajjPl++LgWcKRZF3M80IFF2fE78I80zVow4x6Ei+EyrvObmJ5necXKkRA7o7h/7Xb+ATy2h0ZCdr/OXpmR/yGASfUdNXDrtQ0nYF6TNz1Xqadi9cGv7YKy8SOgbB0SM5S6aRy+ouoaUwNCSsWDleAgEOQvpzq6kCgYBrPv/xMmaWHTBHXY69PPi3MWJjooZxJRA+ppnL9XKmOaZq1fOJ7VhLmNRODt9P5r/UqomEsuUvN+8WnIDcNSltHPEbVBP4jOioBjSP7pEaB4sXVmA9i4iyNvjORAj864lysXY1dgTxQzM06MSJfJQsKNjjDhmRvwbZk+eS8nzGMQKBgAFjAipbMZ3bVShmyMpKL9I2OfNuacsbTFBgra1FMLoRNH7Yre/4/ChEqLffIiRZeumJZY6CNsPrQfoQO/O4hQLk6LY9p1+nw176QWsiNb7sA1HK9pXGAK9mFEx8X4ntfvknd1ikDaH/PvvTbbtlqPkKpAHqtLJXjdwzx7cf8cwpAoGBALxwuNYA7NBV8qRzTsLfSGoZEfl6jQogD3GR+EmFswIEYzdp8Mp+VwcpBjP5D28v9kFKa8dCe7TU9aY1JZm5W+N3ZqfhLp6TNepKVpRsyKsF4Pjz9fDZu1Q9AU81ImSO4w6FkLqQc069w7M5O/tT4/WjYbfqEp16UkP77Gh1F4O6" + ], + "keyUse": [ + "SIG" + ], + "certificate": [ + "MIIClzCCAX8CBgGEV1OLDTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTIyMTEwODEyNTgyM1oXDTMyMTEwODEzMDAwM1owDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGUjByFRmqK1bwX1WM0wB81zu/4pcXI7cv4WshQAdwtQpBJynmCLNoVL/LNwxaxtuhgRUViPh1V/MggrsJLA5BeJAemcaTVfzQsLePh79Ra/wOfHlR5K4l2o5ThPS1JL60ndOGxhg/kqZQIAsHkM1XBxeSMuG77CCfKMOViie3RrSZZ1NnXQRHY2tioZRVgXap9mAnb6bixhGDRq+fwDQTOnr3L/21N7VXauuEz0gtd5MP0InCswFOh/uJPK3iAIGhIbbnam+rFiPRtCYkj7W/fKbE2TBY6Bm/cqYThbKEppYwNzs6dsA1ZbVf88pPAMOydiPBDgnY3F/AXZJEHOqECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdo+c58iEquMpcBiMQ44lhSnroyrRwHazMxQ/8fHUUh2QxNwlGynGPfhMNyUtn06sPZqabV1ixTDfb6NbEpJK/HN3meWUNl4I4i5Zabew5DuUCh/BLRUbgOApsoRyHabDlR68inuXIPaP4M8lOfQsZO2/xNuGnr/eedKIR1WotXtmm2WJv79A9tJQkplizS78HoCa+HlyP1UAuAUDO0IZsJwY8CbKq1wgrhs9by8amdzZRBVILuDnuqEqeRxSY4o4BOvtM7TG5aA0iBVQc473NT1IvY10ojW6zs/ahqs0yG44+W2aBG35DvoDNVqP9Lw1vaTAD7OHdzQGhREz07cemA==" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "da244786-6bf6-40c4-b7c3-094f883d969e", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": [ + "6ee413ed-3b74-458f-acb7-a89d5e05f0b9" + ], + "secret": [ + "sANwaoZOUoMcaPlAr5U1sQ" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "1eeba879-03e8-4aad-b91a-0159cf513d73", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEA4FmIA8jfFAMVm8BuINWDWCn//Xzlk48yoUly1kP8RXriGOYfXrQQTqae0nhBBqlaJFBXAjI41UGJE9+4j23/aGp8vcTTUy9M4qBl9jlt9Pqz178/KaMDuBkeb3TV8PbR6PXrCSuWOuT3LJaXWEitpeMM/+dFSOxD4M1LWOwoQltSlmiZblcb5NsRal60sHvFUA5ecp35jW7Rj+xAQKR7QxgOr8rf83P9NPWYww4+lbKdbgnD2IMfdzZ9soSiHX4WtRrl1dPAqnihfEeaOoDXXTa1m49Q4xORnMVs6E15A+Zviu0xhR1385GT7sHLhZbSh+oLH4nx9jFinry+AgGlUwIDAQABAoIBABbvIBfe82r8y7sxxzBFE1myZXBY0bEtbMwPEZW0unex0aYg9Cj+uEIKB2dVkrQnIMdgjRx03Nl0CxrEfn3vDTJz3E+b7Mxuo+nw4qtygHqQHE1cSA0uFGW/75wOMgahfKDXbtDvqzpXCKt+s3b7awDvvnb0geEsAd5bri2napApy7qEg8iD04NhJhPj+nnoZ/jWTs3N++Dy/a0Y4/TsmIJXjtOY4JUcbYSJDBgFW0hikU/JKRMYXRZNCOzgDlUO+ejxKR2/HJjNK3ynf8Z5seROvVLI6sDTAA20b/PQLW4yEC7BtjWor8zag5tN6ZORdf4tZrsWLAiSAU2NPZepRx0CgYEA9duql4nPIs9Vf7GBZeVJd8Vl5z4WuAbaLgZ0TxaUwU83b9oaw1JmQgZ7gOCDgBkdECJk7iZAgdCCDKyFZyq+aeE8jn2uWXXrh/nMw2rXtAu3K464oyN2kWd4d7vinEsm7B5Vz1tiT20uuACS8AWi63pdBsx7yIsoq/yTantSMN0CgYEA6Zq7A++W2vwCWf0bzuwZ8ozObHafr3awgnEzlD2CXUW0mBC3ptxbo9+ug9SnZC7UMVNEqTVArd2mFZYEnDZGvGbsiN7Qnfw3foKdNpvxMP+CfuQw7vxmCa1JOd5nLz6zKBEPGjIuCy0+wB6ASpUQNxUQQkQoC7L8Qt5cysUSM+8CgYAiSM6iMSp8bTM8ClHEFtRG6nUKaSMb6IC2WFoRyVFXH6fYZi7DPBNcc7D3SNetnlLqNBGlEBqAv8XS5J/5wgEpnKooKKiOex4sKQ5/1b9csSGK5m0i+sgHAMnQ0JeKOgSkepp2vwSXlN8l85aJ+A8/DSI513wPfDBgw2j/OVE91QKBgCnanTNBVAf8Kvewj7DtQGDitYFdZ5LqcwmL+q/OrXLEsGymYiE1Tf34b64TBcK/WSlVP/IJJoOAOOeZL05FszrCPhLvyPTlYZP7FuvX2MjsnpbZj6Lh+e416+7AWEBwvWyqUchhwTojayDE1juGpZcY4Qbea0ZdVTEt4fY6hN5lAoGBAIjrfcjMELZqlLEECwjvTgPmYqTgyJKgVw/SrYBvPpNNqVeIwb62FK19BjXuoIjecXBX8jvefGNa6qTw/OjZLk7JNNbbOdJ1PFp8GkD+e0PPUoISSY0+rAq77geLLfZbcZUwoE0UqKwSYcz0w549aUVKc/5x3tHOxEb7UcWWS5DY" + ], + "keyUse": [ + "ENC" + ], + "certificate": [ + "MIIClzCCAX8CBgGEV1OMBzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTIyMTEwODEyNTgyM1oXDTMyMTEwODEzMDAwM1owDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBZiAPI3xQDFZvAbiDVg1gp//185ZOPMqFJctZD/EV64hjmH160EE6mntJ4QQapWiRQVwIyONVBiRPfuI9t/2hqfL3E01MvTOKgZfY5bfT6s9e/PymjA7gZHm901fD20ej16wkrljrk9yyWl1hIraXjDP/nRUjsQ+DNS1jsKEJbUpZomW5XG+TbEWpetLB7xVAOXnKd+Y1u0Y/sQECke0MYDq/K3/Nz/TT1mMMOPpWynW4Jw9iDH3c2fbKEoh1+FrUa5dXTwKp4oXxHmjqA1102tZuPUOMTkZzFbOhNeQPmb4rtMYUdd/ORk+7By4WW0ofqCx+J8fYxYp68vgIBpVMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAwPwABXVkSlRYqA9sMKJrw9piGH8tkwf6wQeAFhQsInbDzXLeuLt0A3gSuh5nL2zOGcxXddIK4IgUSqI+DlFlFsSkVqHFrQBAdIVRXsYFvGbARKhVuInHlpaOy6Y/VC6opL1BnqsmUOPEv7pk4Nhf/z7y5yZfTUaGiD+K1KA/mEf56NytOFJYsxiCZaAGX6BYIavRJp3YKPAcsNlJS//1G4meOlYcx5HiTA+qY/spc7vPeKuowSh3v26x4tgypLqoD0BAS5KrK4PEVaQM0IcBC3jrIY+7dGbE1Z374nm+1FDU7md48TJdI0c75r60cpBnHUH2bLJo2Z0ezrEojP6mvQ==" + ], + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "95570b1f-da9e-42a0-9532-aa9b690b04cb", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "854f25b9-b37b-468a-b8ac-1e0da29133ba", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "basic-auth-otp", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "ebcd0954-f08f-4c69-970e-43569320bb07", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "cd4b03ca-1a0f-4a9b-8bd9-388e0459d7ac", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "692bd371-d43a-440b-886b-2a0884dd5b9f", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "dce38371-4f6b-45d1-94b0-5e91182c31fd", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "357541a3-2499-42da-9ef0-db129f38f39b", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "9c37a124-af5e-44a2-b619-b3a88e1033c6", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "94355d8f-b66f-405d-80e5-55ec030fb18c", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "8fcdac85-ec7e-4a3b-908a-4f00978d4724", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "cd9ce79e-ba0b-4d58-8249-40f8b2139a56", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "40f9ac10-edc0-46a6-b020-ba1785199911", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "0ac19480-8675-4679-b222-64508c62bcdb", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "9fd2aa99-79d7-435b-a852-5c18fad28546", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "da0a8a3d-9643-4746-b42d-2e8c915f76e7", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "5eea7962-6fe5-4b69-8401-313afd0f6559", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Authentication Options", + "userSetupAllowed": false + } + ] + }, + { + "id": "f80d7c69-9314-4f4b-a61a-28a73e2d0879", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "deffbcd6-aa05-40e2-9bca-2ed50be54bd6", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-profile-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "0b06e91d-77f8-4d8e-a55b-21caf478524a", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "d51e394a-e9a8-495b-ac30-3adb1e66a369", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "3c1657ce-3153-4718-bbec-9d0c508eb8a8", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "70a33e93-226e-492e-b119-f164e2cc457b", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "parRequestUriLifespan": "60", + "cibaInterval": "5" + }, + "keycloakVersion": "19.0.3", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} diff --git a/src/main/resources/baseline/20.0.3/client/client.json b/src/main/resources/baseline/20.0.3/client/client.json new file mode 100644 index 000000000..d555d4f48 --- /dev/null +++ b/src/main/resources/baseline/20.0.3/client/client.json @@ -0,0 +1,45 @@ +{ + "id": "8a641514-bb92-4a5e-8ea4-27b90ef3e637", + "clientId": "reference-client", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "hzjJYnHVxMf3I3ugD4le0CgT1iI3rCx2", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "client.secret.creation.time": "1676457441" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ], + "access": { + "view": true, + "configure": true, + "manage": true + } +} diff --git a/src/main/resources/baseline/20.0.3/realm/realm.json b/src/main/resources/baseline/20.0.3/realm/realm.json new file mode 100644 index 000000000..ee28d9e47 --- /dev/null +++ b/src/main/resources/baseline/20.0.3/realm/realm.json @@ -0,0 +1,2188 @@ +{ + "id": "REALM_NAME_PLACEHOLDER", + "realm": "REALM_NAME_PLACEHOLDER", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "c1c757e3-1483-4a13-a650-57d13762063d", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "a63b0d92-16b3-4110-8dd8-b25ed575035a", + "attributes": {} + }, + { + "id": "1df44d36-8c3e-47a9-8b37-28b31c9c5fd1", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "a63b0d92-16b3-4110-8dd8-b25ed575035a", + "attributes": {} + }, + { + "id": "03ee0166-2480-429b-bc22-8f6fcd4f8126", + "name": "default-roles-REALM_NAME_PLACEHOLDER", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "view-profile", + "manage-account" + ] + } + }, + "clientRole": false, + "containerId": "a63b0d92-16b3-4110-8dd8-b25ed575035a", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "1305643f-47b2-471a-95b0-42f962443c0e", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "deb716da-2b9c-429d-a23a-21e3e40caf11", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "be59b49b-4a79-400f-a67b-0a17903155c9", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "9b2e7245-5859-49fd-a3b0-aeb215dc6e12", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-groups", + "query-users" + ] + } + }, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "7e010c9f-565b-450b-a222-0122ab71010d", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "92004b3a-9187-4f73-9169-319dbdec02bb", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "696b1e73-b5f0-4990-a00f-943a53ff4555", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "aae4db77-9a27-4cb7-b6f6-3f109f553502", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "e2fd690b-88be-4953-8bff-3225e40fdbd4", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "39b3b817-bea6-47f5-8b34-4fc32211e433", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "2615c6ce-7dc4-448b-940f-26905a99b25d", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "254a5871-81e9-4e96-b6a1-cf6c27d3ddb2", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "81582a5b-5be7-45be-9c0b-52582ede762a", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "322ce24f-42f5-40c6-a8bd-d31734ac9834", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "30e5d91d-ac17-4812-ba11-cba05e1add77", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "view-authorization", + "view-realm", + "manage-realm", + "view-users", + "manage-clients", + "query-groups", + "manage-users", + "query-users", + "view-events", + "manage-authorization", + "query-realms", + "manage-events", + "manage-identity-providers", + "impersonation", + "view-clients", + "create-client", + "query-clients", + "view-identity-providers" + ] + } + }, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "c21b3f56-ea00-4e69-905d-88fdb6e78dfa", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "93612d37-df0a-4898-9c9a-c01afb1249b8", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "1e59ed3e-a91c-4ee3-8b29-a8da6c035549", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + }, + { + "id": "15a8e4ef-f406-44e6-b4dc-21fdce6fd023", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "61f1ed79-6efa-4109-9051-cd26de56f538", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "ed91f070-bce3-4b4c-a1bd-066bc96ff3e0", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "db9b8810-7b16-47a9-8b9e-8de58449c206", + "attributes": {} + } + ], + "account": [ + { + "id": "f583ff69-51dc-4c6e-8a1d-addf142c3220", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "9ac5bf5b-bb5d-4138-b397-04ea73622a60", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "ab3ce8f1-ec74-4a35-b00a-259db0bc0878", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "6907ab95-1c60-4f5b-912b-ee6d5c98346d", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "073dfba9-b2b5-42de-a147-e0ac00b9cd76", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "e9989640-ed85-40e5-86fc-51473fdafd4f", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "d5b8032e-e9b2-44fb-8354-ac3e068fb6d3", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + }, + { + "id": "93560eab-3dd4-4ff4-b252-6f6c2103ff31", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "03ee0166-2480-429b-bc22-8f6fcd4f8126", + "name": "default-roles-REALM_NAME_PLACEHOLDER", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "a63b0d92-16b3-4110-8dd8-b25ed575035a" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppGoogleName", + "totpAppFreeOTPName" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "28e61d0d-c4dc-4a91-8012-1a2f0325945c", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/REALM_NAME_PLACEHOLDER/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "a1797864-8592-4d75-b2c0-af15ca029abd", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/REALM_NAME_PLACEHOLDER/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "7e32f2c3-d9fb-40e0-a618-fb68c921f9d9", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "bb4d6126-c9c3-4c39-8016-805d04d55829", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "db9b8810-7b16-47a9-8b9e-8de58449c206", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "61f1ed79-6efa-4109-9051-cd26de56f538", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "6c009e16-d012-43ac-9093-ce95786c2cb8", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/REALM_NAME_PLACEHOLDER/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/REALM_NAME_PLACEHOLDER/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "84f24df3-9b58-41fb-a05a-e591fc47e9d7", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "aa08b21f-f33f-4079-be3d-1e925b44c935", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "ab4f2643-cc27-463e-bfba-44712cffb45e", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "bcc3ec1d-d4bb-4171-82c3-e9b7f2de7371", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "804093f4-8a08-4cca-a1a1-6008b7695e92", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "17a68f02-d8dc-4771-aeeb-d6e262e4fd07", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "bb39a86e-661c-47ef-aa54-d3d2da043340", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "17d26261-10f5-4f60-8cf5-c4106af3a3ee", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "4a18f46f-63ac-4577-89c1-caa895a05255", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "c91c9396-3cca-48c7-93b8-e93567f56f7e", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "888660e1-577c-4249-9703-e86241b9e714", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "3ddfe32a-e127-4808-8f59-a7ba97345258", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "ab023b96-89e4-41ed-b923-288bac047809", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "010b1c53-3403-476c-904f-81f51eaf297a", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "558d8acf-56c5-4011-a366-f4370ebfaa4c", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "5ca091f1-dd75-4f51-92cf-8fe52e1bd91a", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "c77ea1c7-af58-4fe4-8760-d5fc367a537d", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "8aa68575-a903-46ae-adb7-43b4c5573f88", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "319c76bc-93b5-4f78-b371-760f01143ffb", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "682141fe-c658-4a27-9c4f-d12cd6fd639d", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "31285f11-a0a0-4e95-a204-acda390961be", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "ee8c508a-f021-46c8-ba42-9f32b32aa504", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "6aad901c-f1c7-46d8-bfc2-ddd17b37e73d", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "72f7e384-849a-475f-ad2d-0ea19319edd3", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + } + ] + }, + { + "id": "204b6707-5432-43d6-928f-ed17669edc8e", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "6ffca153-999d-45dc-a98c-37ad1f79b04e", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "c8e75ea4-0006-4f7c-882c-8f1499bf14ca", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "24c8b752-95fa-4b11-9c99-1da3d7028783", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "07b45364-f53c-453f-9d6f-1122586e8633", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "e0c34249-b2e2-49cf-b414-9aac15acd82b", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "fcf43c71-170f-4c04-90b5-d6aefb16c7a5", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "88097d77-681a-4b3a-a025-92fae6182a15", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "ac7c6a5d-9d21-4712-889f-951ba412ced0", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "9f08ee07-98a9-496d-b90c-897b38bd2dd3", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "6ba80bef-0a4f-4be1-9e34-89f1a9c8c976", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "9e774de8-10f9-4c1f-b70e-242f07532cf7", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "2086dce7-3707-4101-9174-7ca97082d228", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "7da3ae82-c74d-456e-a1f4-23f5d2ad6919", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "fc6af199-36bb-4721-8805-65b15ac23677", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "4eca2c9d-3fd9-4798-a96f-66ab020f0999", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "a6493944-7b42-47c9-8161-15bcce5e1dea", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-full-name-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "saml-role-list-mapper" + ] + } + }, + { + "id": "20f18ede-0082-4211-8193-97b3faf58832", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "59fd957f-035a-4381-ba69-b07befc54769", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "b5cf58aa-ebfe-4da0-adcf-ad3faee18502", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "acec3143-8444-4d8f-9020-5fdd1992bfa8", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "6555ff94-661a-4659-9cde-0eb2147892ea", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "f957405f-8f50-432a-8ade-8805d27e8b04", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEpAIBAAKCAQEA68PJqiC6cMTIaFvxsnhkyHXiOuwMxa3Udvu3lYJggl+3hMK9Pn1x7ojApUEch53qCIDLJADmr93aofdylZlLLdK/8vDViq8XWnodDfVDi6FttLhGhWiO7e37KswQ2wbosbQFbWIdU8brbsH1sm7snkwGTUuTXt3RDmWOlamomlbeumxNo9SaG+SSMdqwzB1KAu6IQwARvbA8LvzfMhlc6jh16o7CO1QTNFlbZ/8RDmu0T/pOF9TUccsw0hPiFbGzVy7+lANEVFXY9Un0sZTtb3xhJ6l9zsn07ZZEZ6D4COY0yGROWD5bvNUusZvDuzkg75myEHNDb4iZY0+DaiVRwQIDAQABAoIBABaWcUWOPCkzWTtSWm4tsFjaSRyPDUw1HW7G1VhgH4HuIgV4qNaKAIveEzg3QZX7+vY/QfccP6hoGhsRZit5/noQlRj1ROg0DTSQZXnhs8vMDALX8tMI6O9XsQwbyp5JY6rUI1RO+vNR/Vq6VMv4ak1iMupd4WvMgaEeTrz8/lfG6BxBcCGx8Wpvxsd9VvcAyPqXwI2C5y0JSnOJIHRxvLr2NmQeFdFppcVlucQV1SCzxnbMRcI5i0RKuOo/9yJJForwFJcFzkAxWgeUnJglNw/C/20s0aKwM+z+mBAFK/uZPjvEVcbTXj3KM1iuWs5l6FW03YyI5xO5EC2fRUmUKWcCgYEA+Yx2t6GSQ6YJ/v4DhaZv2rzEtn5G9Nk4J98w2GiQAjW4SBRp+vaWrmWhvkvrpX6lp741k9jK6CViayEE05orEHmVjHM885AiddQc88zxtCpGijMR1FuVdklswd0LnyB/PLWgr3f7Z1qAYyFCbxnpcg76jpQCpo36h40KEOO80BcCgYEA8dwZ1/Vwq6UDJBvM9QBvjOnW7Jeoico2m2Hsd74v9G1si+yywyvIMphVnlqoHsXqdxi79ZHJXiyfB/zmQWO9dEhcxq2OubaemDzeJLwXRcLW+Cg4VNIirDdZEWo/nhD7P+00IP/y8Z5neguWYVc01sLkCGB46z8Q/8R59xuZ++cCgYEA0/F9framD/h8MuqwORnDlEaQ1+HmB9xZOlvwE0yzSn0vl2BnJnO6REIjHglDCVrH/PCqdnhA1OuzbAMuIz2j56kr346cLMy0x9gwAsyEWB0zrfpz4SUrirwPt5MyZKLoDbrAz2aaygvuUMMVtmCOiYW5PdDtc2HQbsHV08RoP18CgYB09fi1fCcxioobUypprP1FCux529mQUO7Zc6CUQ7ATJzuf6yaDxc950DtPag31W8bIM3jqB8d2uGNrzHxZUO+UpU3gcpwb6VmGy6Ct6RvkC5ZDycd8FWbZG6cCCfyb5yBpyL812jDVccIevi3KAw81cGgwON8g/I2u8of83Sc5LwKBgQCtVDV1OHE24Y2DxRAakZ5fMp3NYIE8Y+5XrhwHdWRa72AaAz7DrU12b7yZJH5y/upV4Gv12Ia1o1pAx9mXSnVb0WSHp1A8UNtCVlivtnr66BGb5X5ucw53Wz+ciL3KgoHm5pU7Q/6UxttWyikvF2uBp6xMBWOcv3b1f6erxcw2aQ==" + ], + "keyUse": [ + "SIG" + ], + "certificate": [ + "MIICoTCCAYkCBgGGVKQ/mjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlkZW1vcmVhbG0wHhcNMjMwMjE1MTAzMzE1WhcNMzMwMjE1MTAzNDU1WjAUMRIwEAYDVQQDDAlkZW1vcmVhbG0wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrw8mqILpwxMhoW/GyeGTIdeI67AzFrdR2+7eVgmCCX7eEwr0+fXHuiMClQRyHneoIgMskAOav3dqh93KVmUst0r/y8NWKrxdaeh0N9UOLoW20uEaFaI7t7fsqzBDbBuixtAVtYh1TxutuwfWybuyeTAZNS5Ne3dEOZY6VqaiaVt66bE2j1Job5JIx2rDMHUoC7ohDABG9sDwu/N8yGVzqOHXqjsI7VBM0WVtn/xEOa7RP+k4X1NRxyzDSE+IVsbNXLv6UA0RUVdj1SfSxlO1vfGEnqX3OyfTtlkRnoPgI5jTIZE5YPlu81S6xm8O7OSDvmbIQc0NviJljT4NqJVHBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHTSxIteVa2a1V4pqCHweJTRxoXOGE6048ZtEzOsO/5xElynszVZ1iMXlRq8uNTlc80Icx4hw17attP7KCColFIwZ0HCq1IfLQEquoHBaLDhIhVQ7ehCTkto/u8nLgfZL+NDkO+nT+i5eNctMQG74x6hTV3Urc5z4MnBtJNqtPvR+Lw0pbtH07f+K345Z06nxES0Hnb6TLsw8BuTTKPfSqVIAbsi4n3pUgULdeVRd0iYaSQdmwRaFEntWzUJlM4GjvaIPkaMS1CwjEBuutLzskVSiFlQ26W8KwXn7ySIBlec4ox3VD+Q7YynR64bB6Hs1MmFFuooTjn4c02uytLmK2o=" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "d0d08daf-ba76-4e82-8183-37aa8f9a6af1", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEpAIBAAKCAQEA6wG/F8mo6eXBXSuShH9D2ybnMNUfh9dbRJ+Bporl/XNOSxBKaiyo+2W1VIdrjsedwmQuQoFjs2f229qzBS9Fl4ChLxlIjJEW1U+bPilRZUDlSM3q2HE6O4acP+nSIG8ZW9/KhXPgcanM+MixkM9cHzO7bqGKKcnCKD5Y8ia2Vc1PXPNguxmDwuj9XSlpdDOzRZiMUZzcqxzxWgyfUTD839NN16AM6tN4CBIuK779Zwah0ym4wLiVdX2UCJNVzVzuo16YoXYOlXC+skiWG+M4pjj3/IKkLQvzpO9Zh1x6NNMsstGQhPSRUq4KX4fquQVDwxDvIzsIWn2pcTmkOsdWSwIDAQABAoIBADCrTWx7PoimJOwLPI5FHwPxZBrIYH3M+2FUWVDo3iWlrha8mnSvqBVcZHfLjdple8YI4k2ypze99bFlcwLFXfe402jCJzS5TY3CrUdr3igGjxWLU7IcjO9L+ur/nR1LdOiCidome9p+TG1Pfvqa/xyVJaGNQeRSnOuhseEAZG2TMEidK0nWI1NQdm5Q6hsNI2UcPbq3+0ouHz2xBYGoKln76Ibqk5yfNty60jtxeQwg1P0I5PjiyLIiOQUKzaGEX6NENr/WI0qXLr5460ioCqI3Urrgml+lDij/Tg5BXs/Dd1awbup3/vUId/gd7Hy99tXDOK0iXyjZThfgBhsBiYUCgYEA/5zJhrn3g3YyFhPljP4xQBP3k4f/sPBihNwshsa/P8DBIFvxBE3jL+u8QZ/d1PU935gq4183HT8Nk7DFoQ0pntdLyJxfZ5oF07d0qYoHY++R5OIqX2VK2AXBGbwuCUct/XXjEUn83MSBgg1GGbY6qyty1UwBqQhN+qqiOxcUfS0CgYEA61z2IBNOs0T+ns4SsLZERM7uu2mV0IokaLQ60Rbk+7+sV+Mx0eapp4rXuxE33YFRrsvHonyfvbNZtqBnyw7fU8PQm5ozl9T1jeUAdgqm8l5cqpYswASL/NkWLkK3+D+ynLLjKygDZqMj3ZMO8c7nYw799QQaw4T9pzpJZjJLfFcCgYEArOk11kKEsdRJy2+IMBlf3ZXkO1ObXukt6+w43q8hfpH40tf/MUcy8R7JiacIW9/ODCwWjxrA4LLfj1HcTrblucKwTDOjwiSJ3o9ShsGNgEf2bFumCEQwHfO+jZcjmTkiXjvZ778aI4l2hjBOhGQmSdYpZyp0URECFxhIiCpzvL0CgYAYrtodCQlS4aR2URRCtgq40J7Wxr7wbNxeorAcZ3NCN5rCaNA7vB4EtRnkw2yBbWN8mmBoWPuDsIBzF6Vq9TdUmI+TEfvhK3NJG0AOIRXbCyxas38j8BYiQT4DQfn7Ler0ZgpO51Zb+DX1sct6boFzsQnPHUwVPyg+1m0GK7Yg5wKBgQDCIYvL6JhJidgP9ve3U0d0NUDAndRE5fuGqMcKvBiiRAE2D8RxHIWDre/NzrSLAst4UzmuPLG1LB1mIIfUHoPlHX5yEHbBRWtKeJUZ8tEU2z6uNZxP+ntf/K8fdkBS0jbowfG2G/nqqlyJuIrQduNvtT6aoZK0UjRtZ7iAdMjs5Q==" + ], + "keyUse": [ + "ENC" + ], + "certificate": [ + "MIICoTCCAYkCBgGGVKRAEDANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlkZW1vcmVhbG0wHhcNMjMwMjE1MTAzMzE1WhcNMzMwMjE1MTAzNDU1WjAUMRIwEAYDVQQDDAlkZW1vcmVhbG0wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrAb8Xyajp5cFdK5KEf0PbJucw1R+H11tEn4GmiuX9c05LEEpqLKj7ZbVUh2uOx53CZC5CgWOzZ/bb2rMFL0WXgKEvGUiMkRbVT5s+KVFlQOVIzerYcTo7hpw/6dIgbxlb38qFc+Bxqcz4yLGQz1wfM7tuoYopycIoPljyJrZVzU9c82C7GYPC6P1dKWl0M7NFmIxRnNyrHPFaDJ9RMPzf003XoAzq03gIEi4rvv1nBqHTKbjAuJV1fZQIk1XNXO6jXpihdg6VcL6ySJYb4zimOPf8gqQtC/Ok71mHXHo00yyy0ZCE9JFSrgpfh+q5BUPDEO8jOwhafalxOaQ6x1ZLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEkOE5zWi8x3NfPWsdZkLckRw9vQFDYhQuaRZfD1i3lKvYW9xERFjOICuSHUX9yxX/CpGWVDAomXXXYxvlPpkENO/GjUGcL5UH6AopPkOzUZwsVWEylR6nczlK9sXjfjqgDOFwV19q5bn6hiV6qLG4Ty747lCATaxCUDPwJvZE8ZLFTHrccFtAH8VXCZbJJMLXO42LgMeG5nF4Tf1K0iI+4sSDWshl+QNugmaRQSrG0IklH4+U9J9JTwAiibkspgVsc2ubhbA+Xvzndg0vIQ2cEVWLqK9tRAIuaoANTmJneBZdBoVL5gtY3jCyXj6ecrKr+4JzeXCwmrxQUk9061eDU=" + ], + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + }, + { + "id": "0d0237f6-29a9-4e1d-8de0-0490ab1c9118", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": [ + "1523f166-af8b-4970-94ff-eabb0f391532" + ], + "secret": [ + "ByJpObMtnXpqZwygKnj_cgP-SkhVJPH_D-vgOS8yRSH9Km9idi4Ryh5w__zKGk4OeIJWQWRSz5VG_6kzINchKw" + ], + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + }, + { + "id": "53a26567-105e-4b11-bbd1-1516fe76104a", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": [ + "8d1e845c-f3bc-4b6c-86c5-acbc49442386" + ], + "secret": [ + "EWEleDkIM15zP8tyIr6nHw" + ], + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "c3820085-85d3-4ff8-bd42-15464fa668b6", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "815709b3-7421-44b3-bf18-4838cf354852", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "basic-auth-otp", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "6b97ee19-cc94-435d-92cd-c16cec1ce04e", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "8ce4d49e-4ef9-4f99-ab46-3693b7b4a093", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "2d7a3dd7-cfa2-427c-b1c6-aa91a4cd6c63", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "bf73abb4-36f2-4338-8578-86ab06bb1131", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "65caf860-42ee-4bbe-aafe-468c838cf602", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "bf7960c0-0247-442b-b381-bea5646a4912", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "1f2b94c0-0f10-4484-a224-0699141f7c02", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "a34173a7-4ad7-4817-ad11-9ddc459854aa", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "a69e205f-6ae1-4aa1-9ed1-806dbc5f7168", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "18b4d1ed-9fcd-41b2-8db0-cdc74d9ad155", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "7aeeddfa-01fa-43c2-80ad-3d7089b8d952", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "4e0d5e38-0c28-4ad3-b904-e1dcde038e7f", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "c14d77a8-4c9f-429d-9d75-fd5d5046e140", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "e58d48bb-d404-40d9-9cfb-5fa5d450fef1", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Authentication Options", + "userSetupAllowed": false + } + ] + }, + { + "id": "287e7e9a-1b9a-40b8-9d96-2718f336c12a", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "bad61d64-c8fb-4dad-b8fe-ce25da2de253", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-profile-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "68449dd8-7be7-4150-82fe-fb75b67c896e", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "baded0d1-49db-4723-8924-19f1c6e4b0d3", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "c8e1e585-b8bb-417c-943d-079afbae72c5", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "07e5d37a-e1ed-4957-9802-f02b8565c715", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "parRequestUriLifespan": "60", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "20.0.3", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} diff --git a/src/main/resources/baseline/25.0.5/client/client.json b/src/main/resources/baseline/25.0.5/client/client.json new file mode 100644 index 000000000..b96b479b1 --- /dev/null +++ b/src/main/resources/baseline/25.0.5/client/client.json @@ -0,0 +1,59 @@ +{ + "clientId": "reference-client", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "cjQ7lt37eAxeBRDzmLDsML89l1F6MHeY", + "redirectUris": [ + "/*" + ], + "webOrigins": [ + "/*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1726783534", + "backchannel.logout.session.required": "true", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ], + "access": { + "view": true, + "configure": true, + "manage": true + } +} diff --git a/src/main/resources/baseline/25.0.5/realm/realm.json b/src/main/resources/baseline/25.0.5/realm/realm.json new file mode 100644 index 000000000..463be743b --- /dev/null +++ b/src/main/resources/baseline/25.0.5/realm/realm.json @@ -0,0 +1,2355 @@ +{ + "id": "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "realm": "REALM_NAME_PLACEHOLDER", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "9580c9da-0c78-43c6-82b6-f1694db9bfa2", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "attributes": {} + }, + { + "id": "480c5735-3615-4031-8af5-1a5941f6ed85", + "name": "default-roles-REALM_NAME_PLACEHOLDER", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "attributes": {} + }, + { + "id": "acdaa4dc-3b37-4ef8-bc96-61d0bad24273", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "cfb49ecc-087c-45ee-82b9-c04f09598ce7", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "6fa23d54-426d-43fe-8fe9-1ea3eb901101", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "98f722da-2e2b-4607-9cee-cfbf53593f36", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "831f2cef-957c-4eaf-a309-e04ba25aed17", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "ad3da993-2344-45ab-adda-805025fe1c0e", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "9144db3e-b609-4afa-a7fb-86340e7c4943", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "64ce3225-b08c-45ac-b4da-a0f78ff53054", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "bff7eea4-ef17-4873-8712-8461ac4a3ecb", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "a8a226e0-fbdc-4a67-b4d8-53a945fad25c", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "b22b71b1-a8dd-4aad-a879-a266a27f5da0", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "manage-users", + "view-authorization", + "view-clients", + "impersonation", + "create-client", + "manage-events", + "query-clients", + "query-groups", + "query-realms", + "view-users", + "view-events", + "manage-clients", + "manage-identity-providers", + "manage-realm", + "query-users", + "view-identity-providers", + "manage-authorization", + "view-realm" + ] + } + }, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "56940251-b312-4ba5-8897-80770420fbc5", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "8080db13-00bd-4091-a36d-eb9a727c6e06", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "c637da23-2962-43fd-ad60-3d722b83c991", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "77347d4e-c2ba-4590-b9d7-2f6caacfb9c2", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "eee3badf-8cfd-45e0-95e2-b31c4246b2ff", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "62028465-2dbc-438c-a3da-d1028fc064cb", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "c3d108ea-11e7-4c03-9e22-165e27a37b29", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "f104fd30-19bc-41f1-8d1d-8ac8060f4d3e", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + }, + { + "id": "291747a2-0c07-4265-afe8-08a195e6d029", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "09571088-e666-437f-a2e5-1025ab1c2679", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "2d47b1b5-8c05-4cfb-adac-000dff429b98", + "attributes": {} + } + ], + "account": [ + { + "id": "5e1c1bd4-a134-4765-8f0b-753adc507e3f", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "87f66ba3-e129-4b3d-a50c-1dbefb31c3e3", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "21efa0ec-d716-49d7-b987-550b4158300c", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "294862a6-637d-4993-9743-fab2ea7745d5", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "ffd6f5d8-5f93-4824-9bb8-4a18bda8e65c", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "7101cd26-567b-41a2-935d-6dd3c95447d4", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "0b2fda0c-350c-4719-8485-74c4c9a14b4f", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + }, + { + "id": "66746e76-a6e9-4f17-8a53-c8485ffcbd54", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "480c5735-3615-4031-8af5-1a5941f6ed85", + "name": "default-roles-REALM_NAME_PLACEHOLDER", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "dd63c101-0933-44ff-bd0d-6291b7b195ae" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "c9b64036-d306-481f-acf0-138f42e4714f", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/REALM_NAME_PLACEHOLDER/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "fb5c35f5-62d6-4641-96f5-1e92fee5e4c9", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/REALM_NAME_PLACEHOLDER/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "26ccae04-fffd-4fb2-8c8b-a69331675dc4", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "83bcfb18-8a63-40e8-a318-2511e432b8f9", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "2d47b1b5-8c05-4cfb-adac-000dff429b98", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "dabfe89e-a20a-4502-81ae-6effe456c884", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + }, + { + "id": "5e7102d7-cbc5-48f2-855b-6c49b7730bc5", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/REALM_NAME_PLACEHOLDER/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/REALM_NAME_PLACEHOLDER/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "f0dc4884-abd8-43b1-8daf-a4ea30af2c45", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "75c3c28e-9954-4591-ad9f-2fa561935969", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${phoneScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "c1bd61d7-b43c-47b6-bb09-c8f1048626b9", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "22570598-1102-4011-a257-914cf1c61cb9", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "2b62b196-a141-4963-b0a8-7cf1a5e5d79d", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "8103b7d0-9a8f-42c3-8cd4-3c14ab4f45d6", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "0c9b45df-7b86-498e-a50b-263c81516364", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${emailScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "55a6275a-652a-4087-800f-b8a96a18f847", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "5deee1be-1359-4700-b3eb-fda36f384c6c", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "baefbd93-a03d-4dcf-a810-d130c4c52e34", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "d9afdfca-5d6a-4154-9cb4-ffbca2c9a0cd", + "name": "basic", + "description": "OpenID Connect scope for add all basic claims to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "b4274c50-30bd-41b8-90cf-0226c3537325", + "name": "sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-sub-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "9816cb0e-df86-47d8-8c6d-a6e1e728936d", + "name": "auth_time", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "AUTH_TIME", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "auth_time", + "jsonType.label": "long" + } + } + ] + }, + { + "id": "c747bf13-7fef-4210-931f-5b925e66b762", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "${rolesScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "16806ab6-8445-4982-98c5-31d2027eef21", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "f84f3429-cb42-41b1-a1f0-b0ce18547f88", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "bb42a14a-d1d2-469b-ba6a-5de818f9dc09", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "27c4af4a-ba34-4ab8-a3c7-d170c7600ce9", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${addressScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "5fce34d7-0d3f-4ea3-9dd8-e9a935d7afc8", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "54a28d98-624a-446a-bac6-987ef81e94a1", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "d24b73e0-99ff-4529-822b-e34ca0f01e40", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "b8cb435d-b65e-4ea7-9fcf-47e68d12034c", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "29e507c4-0d25-4c7e-bab2-445f02229498", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${profileScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "38069a29-e1a5-418f-ae2c-d3eaad7aac72", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "75e8f35b-c264-413f-8329-6f1f75845754", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "14dbae81-967b-4293-a717-37e7c23849ce", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "b5e39b39-251b-4c7c-a495-f224fa668b8e", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "8524ea93-38b8-4dc1-b1f0-d6a79be4aa49", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "b43b0a85-5b62-4e24-bb44-d27ad870231e", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "3ec07ced-87fe-4a6f-a6d6-3aef1b70bb77", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "279983b1-32c1-4240-a364-e1c5da2d1567", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "1308c0b3-f55e-4073-bef8-5f2ea0b6d7f1", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "ed828254-6168-41fd-95e8-bd0296499677", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "e008f950-539e-4484-9e49-a5ddc19a6247", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "13145ef8-796d-44eb-9f91-6097872f7e43", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "44bd6fd2-002a-4f2e-9f67-85a10bdaaf91", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "af4a8bbb-eea2-4e92-a52e-db1b598cbdda", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "e20000d2-97e9-4963-97ed-29c2493e88a1", + "name": "saml_organization", + "description": "Organization Membership", + "protocol": "saml", + "attributes": { + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "f79afeba-4905-4acd-9a31-f5772a9cfaf5", + "name": "organization", + "protocol": "saml", + "protocolMapper": "saml-organization-membership-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "669d6b18-ad12-4ad4-bdac-2ccc9ba8ec19", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "68c8bb60-3ade-4629-8e39-bacbbf1729a9", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "e2644a46-32ce-4773-a502-4b49047ade5f", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "a16f5c5c-9b31-48e4-9a2a-b1102f116929", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "f4a04ae3-7689-4162-a10d-80bf12c062b8", + "name": "organization", + "description": "Additional claims about the organization a subject belongs to", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${organizationScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "86d3a466-ec88-4260-8666-c80fb8a67616", + "name": "organization", + "protocol": "openid-connect", + "protocolMapper": "oidc-organization-membership-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "saml_organization", + "profile", + "email", + "roles", + "web-origins", + "acr", + "basic" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt", + "organization" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "fd92ba76-e8b6-473b-ae5b-324de55d1bec", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "680d98da-7b39-42d7-addf-c8709f70e997", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "134087bf-1b89-43a2-9ed8-e835bf24698e", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "6093461f-6bf9-47ef-902e-0cc6e795d468", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper", + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "da0f1531-50c5-4c32-91d6-78a49c83c8f9", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "ee589b19-fee3-43aa-a235-6ebad256fc88", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-address-mapper", + "oidc-usermodel-property-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-property-mapper" + ] + } + }, + { + "id": "98947e9b-8db1-43a9-953b-b0a7a6529308", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "19309024-e8ed-41bf-aaab-120b77546970", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "6873ae62-f710-410f-adff-4529edacecd5", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "acaf8c35-8426-4212-b476-9755e750cba8", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "79b45bb7-9f51-4a5d-9ddb-a38193869cf8", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + }, + { + "id": "6d6fdef5-fc2a-4283-872b-78d43683405a", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "820f56e1-92f9-489a-8d5b-435c3090d565", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "485f4929-8cd5-4823-ab43-46632ff328f1", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "7cd25178-93e4-40a1-85a3-a7eedd1eee58", + "alias": "Browser - Conditional Organization", + "description": "Flow to determine if the organization identity-first login is to be used", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "organization", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "13859544-1f4e-4d3a-9c59-160d72f1ef09", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "95b03f52-3e9a-4745-9f2d-fa92024f892a", + "alias": "First Broker Login - Conditional Organization", + "description": "Flow to determine if the authenticator that adds organization members is to be used", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "idp-add-organization-member", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e0b0819f-f839-4ac3-93bc-a6944d789c6b", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "a39f72d5-7336-48bf-9abd-c6247d3c5188", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "d0ebe092-0fd9-4884-9df2-0fc19560cf0a", + "alias": "Organization", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional Organization", + "userSetupAllowed": false + } + ] + }, + { + "id": "7b9d4855-89f8-4df6-beda-bfb035f9a244", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "df1575c6-b9cd-4342-8c85-c6376853866d", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "10a02bfc-f238-4b94-abbd-7706c2f21b70", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "63965b58-1b62-4f3a-9fd3-7e3e3c4c3eed", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 26, + "autheticatorFlow": true, + "flowAlias": "Organization", + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "618c8052-b998-4181-85f3-6e171a8ad356", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "ca3e691a-2326-450b-93d0-eb9929fc3745", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "e8c2f7fe-c611-4ef9-a062-8d6c3388f797", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "178a91fc-9bb6-43c2-88cc-5fd73afe2d75", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 50, + "autheticatorFlow": true, + "flowAlias": "First Broker Login - Conditional Organization", + "userSetupAllowed": false + } + ] + }, + { + "id": "4c38d67f-c298-4b46-aec8-df00f853e64a", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "ee4ae8cd-0770-44a0-89c5-de1bb96971df", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "9af610f3-08e4-4a3a-a2f2-a85c9cc65f88", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "def02675-afb8-479b-9756-b6399c49a616", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "4da59173-6c48-4f89-a8f1-b9ffe3952641", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "5aab6c05-0143-49e2-a8a7-b886685e00b9", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "c00631ca-8122-41e7-bffc-6034063cc7b1", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "CONFIGURE_RECOVERY_AUTHN_CODES", + "name": "Recovery Authentication Codes", + "providerId": "CONFIGURE_RECOVERY_AUTHN_CODES", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "UPDATE_EMAIL", + "name": "Update Email", + "providerId": "UPDATE_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "delete_credential", + "name": "Delete Credential", + "providerId": "delete_credential", + "enabled": true, + "defaultAction": false, + "priority": 100, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "parRequestUriLifespan": "60", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "25.0.5", + "userManagedAccessAllowed": false, + "organizationsEnabled": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} diff --git a/src/main/resources/baseline/26.0.5/client/client.json b/src/main/resources/baseline/26.0.5/client/client.json new file mode 100644 index 000000000..9da0a47e7 --- /dev/null +++ b/src/main/resources/baseline/26.0.5/client/client.json @@ -0,0 +1,60 @@ +{ + "clientId": "reference-client", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "cjQ7lt37eAxeBRDzmLDsML89l1F6MHeY", + "redirectUris": [ + "/*" + ], + "webOrigins": [ + "/*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1726783534", + "backchannel.logout.session.required": "true", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "organization", + "microprofile-jwt" + ], + "access": { + "view": true, + "configure": true, + "manage": true + } +} \ No newline at end of file diff --git a/src/main/resources/baseline/26.0.5/realm/realm.json b/src/main/resources/baseline/26.0.5/realm/realm.json new file mode 100644 index 000000000..68cd9129a --- /dev/null +++ b/src/main/resources/baseline/26.0.5/realm/realm.json @@ -0,0 +1,1965 @@ +{ + "id" : "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "realm" : "REALM_NAME_PLACEHOLDER", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxTemporaryLockouts" : 0, + "bruteForceStrategy" : "MULTIPLE", + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "9580c9da-0c78-43c6-82b6-f1694db9bfa2", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "attributes" : { } + }, { + "id" : "480c5735-3615-4031-8af5-1a5941f6ed85", + "name" : "default-roles-REALM_NAME_PLACEHOLDER", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "manage-account", "view-profile" ] + } + }, + "clientRole" : false, + "containerId" : "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "attributes" : { } + }, { + "id" : "acdaa4dc-3b37-4ef8-bc96-61d0bad24273", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "dd63c101-0933-44ff-bd0d-6291b7b195ae", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "cfb49ecc-087c-45ee-82b9-c04f09598ce7", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "6fa23d54-426d-43fe-8fe9-1ea3eb901101", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "98f722da-2e2b-4607-9cee-cfbf53593f36", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "831f2cef-957c-4eaf-a309-e04ba25aed17", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "ad3da993-2344-45ab-adda-805025fe1c0e", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "9144db3e-b609-4afa-a7fb-86340e7c4943", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "64ce3225-b08c-45ac-b4da-a0f78ff53054", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "bff7eea4-ef17-4873-8712-8461ac4a3ecb", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "a8a226e0-fbdc-4a67-b4d8-53a945fad25c", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "b22b71b1-a8dd-4aad-a879-a266a27f5da0", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "manage-users", "view-authorization", "view-clients", "impersonation", "create-client", "manage-events", "query-clients", "query-groups", "query-realms", "view-users", "view-events", "manage-clients", "manage-identity-providers", "manage-realm", "query-users", "view-identity-providers", "manage-authorization", "view-realm" ] + } + }, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "56940251-b312-4ba5-8897-80770420fbc5", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "8080db13-00bd-4091-a36d-eb9a727c6e06", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "c637da23-2962-43fd-ad60-3d722b83c991", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "77347d4e-c2ba-4590-b9d7-2f6caacfb9c2", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "eee3badf-8cfd-45e0-95e2-b31c4246b2ff", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "62028465-2dbc-438c-a3da-d1028fc064cb", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "c3d108ea-11e7-4c03-9e22-165e27a37b29", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "f104fd30-19bc-41f1-8d1d-8ac8060f4d3e", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + }, { + "id" : "291747a2-0c07-4265-afe8-08a195e6d029", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "09571088-e666-437f-a2e5-1025ab1c2679", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "2d47b1b5-8c05-4cfb-adac-000dff429b98", + "attributes" : { } + } ], + "account" : [ { + "id" : "5e1c1bd4-a134-4765-8f0b-753adc507e3f", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "87f66ba3-e129-4b3d-a50c-1dbefb31c3e3", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "21efa0ec-d716-49d7-b987-550b4158300c", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "294862a6-637d-4993-9743-fab2ea7745d5", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "ffd6f5d8-5f93-4824-9bb8-4a18bda8e65c", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "7101cd26-567b-41a2-935d-6dd3c95447d4", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "0b2fda0c-350c-4719-8485-74c4c9a14b4f", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + }, { + "id" : "66746e76-a6e9-4f17-8a53-c8485ffcbd54", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "c9b64036-d306-481f-acf0-138f42e4714f", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRole" : { + "id" : "480c5735-3615-4031-8af5-1a5941f6ed85", + "name" : "default-roles-REALM_NAME_PLACEHOLDER", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "dd63c101-0933-44ff-bd0d-6291b7b195ae" + }, + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "c9b64036-d306-481f-acf0-138f42e4714f", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/REALM_NAME_PLACEHOLDER/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "false", + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "fb5c35f5-62d6-4641-96f5-1e92fee5e4c9", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/REALM_NAME_PLACEHOLDER/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/REALM_NAME_PLACEHOLDER/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "false", + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "26ccae04-fffd-4fb2-8c8b-a69331675dc4", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "83bcfb18-8a63-40e8-a318-2511e432b8f9", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "false", + "client.use.lightweight.access.token.enabled" : "true", + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "2d47b1b5-8c05-4cfb-adac-000dff429b98", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "true", + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "dabfe89e-a20a-4502-81ae-6effe456c884", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "true", + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "5e7102d7-cbc5-48f2-855b-6c49b7730bc5", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/REALM_NAME_PLACEHOLDER/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/REALM_NAME_PLACEHOLDER/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "false", + "client.use.lightweight.access.token.enabled" : "true", + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "f0dc4884-abd8-43b1-8daf-a4ea30af2c45", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "75c3c28e-9954-4591-ad9f-2fa561935969", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${phoneScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "c1bd61d7-b43c-47b6-bb09-c8f1048626b9", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "22570598-1102-4011-a257-914cf1c61cb9", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "2b62b196-a141-4963-b0a8-7cf1a5e5d79d", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "consent.screen.text" : "", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "8103b7d0-9a8f-42c3-8cd4-3c14ab4f45d6", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "0c9b45df-7b86-498e-a50b-263c81516364", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${emailScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "55a6275a-652a-4087-800f-b8a96a18f847", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "5deee1be-1359-4700-b3eb-fda36f384c6c", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "baefbd93-a03d-4dcf-a810-d130c4c52e34", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "d9afdfca-5d6a-4154-9cb4-ffbca2c9a0cd", + "name" : "basic", + "description" : "OpenID Connect scope for add all basic claims to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "b4274c50-30bd-41b8-90cf-0226c3537325", + "name" : "sub", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-sub-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + }, { + "id" : "9816cb0e-df86-47d8-8c6d-a6e1e728936d", + "name" : "auth_time", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "AUTH_TIME", + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "auth_time", + "jsonType.label" : "long" + } + } ] + }, { + "id" : "c747bf13-7fef-4210-931f-5b925e66b762", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "consent.screen.text" : "${rolesScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "16806ab6-8445-4982-98c5-31d2027eef21", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + }, { + "id" : "f84f3429-cb42-41b1-a1f0-b0ce18547f88", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "bb42a14a-d1d2-469b-ba6a-5de818f9dc09", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + }, { + "id" : "27c4af4a-ba34-4ab8-a3c7-d170c7600ce9", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${addressScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "5fce34d7-0d3f-4ea3-9dd8-e9a935d7afc8", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "54a28d98-624a-446a-bac6-987ef81e94a1", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "d24b73e0-99ff-4529-822b-e34ca0f01e40", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "b8cb435d-b65e-4ea7-9fcf-47e68d12034c", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "29e507c4-0d25-4c7e-bab2-445f02229498", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${profileScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "38069a29-e1a5-418f-ae2c-d3eaad7aac72", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "75e8f35b-c264-413f-8329-6f1f75845754", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "14dbae81-967b-4293-a717-37e7c23849ce", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "b5e39b39-251b-4c7c-a495-f224fa668b8e", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "8524ea93-38b8-4dc1-b1f0-d6a79be4aa49", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "b43b0a85-5b62-4e24-bb44-d27ad870231e", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "3ec07ced-87fe-4a6f-a6d6-3aef1b70bb77", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "279983b1-32c1-4240-a364-e1c5da2d1567", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "1308c0b3-f55e-4073-bef8-5f2ea0b6d7f1", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "ed828254-6168-41fd-95e8-bd0296499677", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "e008f950-539e-4484-9e49-a5ddc19a6247", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "13145ef8-796d-44eb-9f91-6097872f7e43", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "44bd6fd2-002a-4f2e-9f67-85a10bdaaf91", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "af4a8bbb-eea2-4e92-a52e-db1b598cbdda", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "e20000d2-97e9-4963-97ed-29c2493e88a1", + "name" : "saml_organization", + "description" : "Organization Membership", + "protocol" : "saml", + "attributes" : { + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "f79afeba-4905-4acd-9a31-f5772a9cfaf5", + "name" : "organization", + "protocol" : "saml", + "protocolMapper" : "saml-organization-membership-mapper", + "consentRequired" : false, + "config" : { } + } ] + }, { + "id" : "669d6b18-ad12-4ad4-bdac-2ccc9ba8ec19", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "68c8bb60-3ade-4629-8e39-bacbbf1729a9", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + }, { + "id" : "e2644a46-32ce-4773-a502-4b49047ade5f", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "a16f5c5c-9b31-48e4-9a2a-b1102f116929", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "f4a04ae3-7689-4162-a10d-80bf12c062b8", + "name" : "organization", + "description" : "Additional claims about the organization a subject belongs to", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${organizationScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "86d3a466-ec88-4260-8666-c80fb8a67616", + "name" : "organization", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-organization-membership-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "role_list", "saml_organization", "profile", "email", "roles", "web-origins", "acr", "basic" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt", "organization" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "fd92ba76-e8b6-473b-ae5b-324de55d1bec", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "680d98da-7b39-42d7-addf-c8709f70e997", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "134087bf-1b89-43a2-9ed8-e835bf24698e", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "6093461f-6bf9-47ef-902e-0cc6e795d468", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper" ] + } + }, { + "id" : "da0f1531-50c5-4c32-91d6-78a49c83c8f9", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "ee589b19-fee3-43aa-a235-6ebad256fc88", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper" ] + } + }, { + "id" : "98947e9b-8db1-43a9-953b-b0a7a6529308", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "19309024-e8ed-41bf-aaab-120b77546970", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "6873ae62-f710-410f-adff-4529edacecd5", + "name" : "hmac-generated-hs512", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "4f547037-1b1c-4b8a-898f-32beaedbc322" ], + "secret" : [ "qceGbal839MtCUtk-mNlJilhXKT-x0KRIQ502tnI-Jr4pFfJMVeWa9cBBMtl_IlTt_54UY_izBsF8UGVhWiCXoA5OWgwvOO30niNHboRZ0YcD9LweLssQxfDKmYp7yla974jjSQwI3EoURv8skVpKn6S_wGwL5o3l0bwpG99KJM" ], + "priority" : [ "100" ], + "algorithm" : [ "HS512" ] + } + }, { + "id" : "acaf8c35-8426-4212-b476-9755e750cba8", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "174f967c-38d0-48f4-84be-76342436b6a3" ], + "secret" : [ "PROT6xpfFNQmbuO7x-TBTA" ], + "priority" : [ "100" ] + } + }, { + "id" : "79b45bb7-9f51-4a5d-9ddb-a38193869cf8", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpQIBAAKCAQEAw5ebKJIOg4YccO2JtmIc4oBr18RMMsKk7mC3+jNXYjTgPlpMl8b294PTeYNG56wP2yNtqOA8jtdIfJIGM3yOunEwzoRO0u5WKy6AvGdLQvB3By5ceotVGRWqtCWlSrz/xzYIp8n9Kwj86wDOSt0PyZFIahRpRDEGmT/kcH0996VPHoLynhYRUz7ekxLApzQwCMuDkTD58YC9u0USFfvOQohc57mryQT34vqRu/RfPcl7Nv26p8T1hygeW+NNj241spLj17gKA5Nkemg4Sgvlg7yKmimMqGt9CEKKIT4Kakls2rjLMSYEOh5XacenSsLFofK7E1Tf9z0k+EDejCZ5RwIDAQABAoIBADpdLut4SeRtTGdWOlW2CTB9abDE3of3FQgczElYsKaZaKCyiVBxCpjpOV11Et9mtISLmdlesDNfgj3JxRfv/xcbV5kIWg0PGZ9hDQErQYYEA0CdUPMwSIBnurxuz1fx9dEYCpUm7Oi+kdn+L5CfTmqzc4xT8uVqS7HHIv9+H9OZdq3kkID1YwucWUWTDosjKGCu57WY96+M95UHdqQMYY4GCCgQv5OgjjzdC7VWNpffBLZHWHXh2UW9MAcE++40ryydt6LZFFxqJUpxPVwKUhmdP6YGmxlkRt7sVTsGX90zniqFN5CamxidbCO1tPjuP8fwCXcqWSwU3uW2tRhMWuECgYEA7ZDXYxwPlsRZF0ivhbqQVZFHf1jlWLNMLICy5DzwXWCVJRFVt++pQa2dgnQiRL+TfebV6qgGjK8U89GkNPNGe7wdHayWRe701/JuyKCauZc/5lfQPsG4pVZVcbIuj1hAd4gAXAytdmzQ7cBIGwTWBptJPI4DA5ct/rE9O969qh0CgYEA0sT5jJuofPQsqmnnz3KqZ7DB2fTyzmzMo6JdqfQGLwgTSapk5lWqOyNcNuNCeWYaYwlO8ZmAhzg7g7XnTE1k3iDPQhpd1gV0KlgHk549nnD47v1pDPjFlbqTjbvvB9OFYTbRwBIrAlGQKjyCAAMRcWVwxG9h4RvAdk5FheQb87MCgYEAhk57ppmHqqno4EQEj2sRDH8s168vQj1jlElSWbyl+3SN/T3Woz2ICAyaXtU/RnS0ctpdF+PUiBa3lrxvxEvBDlUkdNFMx863d5qkzSIXN1NuGdCNd91XgYnUlomwzvOKxskJwwCb1LbiS3eIjFXoliWWeviidZYzt6kGQGHGAnUCgYEAxtgoatwrn/8o6HlTxmXymDKtIDi0ncUNZ092ODHNZ6+hqr0Dxj6JhJN+mxXaj/eg61BL1ykvleKaW09Q8K6Pe/TONBn170Vj69LzCvSeQ41nfOk8o41Ls0+7h1sHToXi7u0uA5vgUaarcP121BYQ7b97HQfL+vkYoUSE2KV1LXsCgYEAp1llSgSYN7/aU0GNipu0Y9GDBIv2FEz0LERD9bdg84bpFBmT9weFACGMDiH0OXSRR22lZ1V5diqm/idRrEzs80bsIYrStGE+flwbAVIyuyyMt42Pbd65LeWNjYUWYBUVRYzOGyd+DxfjRKSXHgbE7ZdXna0k05IZNoQ2niE6rus=" ], + "certificate" : [ "MIICuzCCAaMCBgGTTfUQKDANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZSRUFMTV9OQU1FX1BMQUNFSE9MREVSMB4XDTI0MTEyMTA5MDAyNloXDTM0MTEyMTA5MDIwNlowITEfMB0GA1UEAwwWUkVBTE1fTkFNRV9QTEFDRUhPTERFUjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMOXmyiSDoOGHHDtibZiHOKAa9fETDLCpO5gt/ozV2I04D5aTJfG9veD03mDRuesD9sjbajgPI7XSHySBjN8jrpxMM6ETtLuVisugLxnS0LwdwcuXHqLVRkVqrQlpUq8/8c2CKfJ/SsI/OsAzkrdD8mRSGoUaUQxBpk/5HB9PfelTx6C8p4WEVM+3pMSwKc0MAjLg5Ew+fGAvbtFEhX7zkKIXOe5q8kE9+L6kbv0Xz3Jezb9uqfE9YcoHlvjTY9uNbKS49e4CgOTZHpoOEoL5YO8ipopjKhrfQhCiiE+CmpJbNq4yzEmBDoeV2nHp0rCxaHyuxNU3/c9JPhA3owmeUcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAwk+tpb2RH48XnPMygvZNuex7EsnE7OV3C5VCq04qcOaFqtstvMbIrYrEIxKzu27NARi4cvHtzr1qjitmX/GpSNEPtA5/jIWjyz5IMPOh7o7J9RCfqFGEthUtfS/ec+JmaDoL15sgnoxWxXsVITLYlzPYP0EUhaJKrWxkBZ/79tfLDhKscpFXf2SRsebkBN3KdMhfVsFxnRWXOCrJbh8pqgal+GD5mdbHB9B+CJ574+tzS8p40JCoiYJp06hqlaEQ6/Pv2sLxQJAIHS3pAnA0EYPRNhFYRc6fWJb6ioSYM339Gux+8C2rFqPKZxQg5vYxPDvplxJvuylynA8NTdyVdQ==" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + }, { + "id" : "6d6fdef5-fc2a-4283-872b-78d43683405a", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEAw+l83QalofaA6cW7B9FPst5XWPaHpWCNwwGEDM3ZxnUo+gynw7ONGShtnXj643oqNDltTvo7e71slJTaKEgbUqu2Zcfl/B97cXV6iMUQJmSr2SXYxHYl/9tBNnLetfpntzLWgY+lkfT1peBcwk7J6K58Ym+lbEZhXf/EAHqB1gH4WTYLWhX5LEzSUTR9UoZ0o/DisarODJIGvE2RVTkRo1cKr09Md1NInWaJM9yDSOp+heFxx6wyqmrb5tylqUx5uHXo3o7RGcdttf1IVYS8jNNaQirxsbxWSJHSdwQKxt92NutcO1tv4tzDvoEeVJcKDoqs6M396k6ywSgD0UoNCQIDAQABAoIBAAD0Ri0D0N+B39oQbuGSEQO1NlLmM7FU6XVyfT4pH083V6rzUAd3/Gi+9am3fFSKgWIeIklcMD+UcJu/DdqPkowYiGh+f/RDNjEbRvmB9c4tRCXOm8h5LgsALZUiTuT8AnCCyUcTeAiTjnUixQQW3IzkxkS3q0qXtsNKcTeMLgDo1CaFDPCQR5HAA6FG2w0Xb3MCa9SOGgRzauO13zoO1B9U4+HGvhVF5k+e+evuAdzHLapvWkDQRkNuXb/ScJAEUzRJ94yPFHgg1Vg/Gg9GVVvMGQB5yX2EeaLMd3N8qhHl2JN/b4vmOQZzpAxWY1GT4Yd0WE0O+NovaMEvDdRVFgECgYEA+8hweFvkTBaBau228yw6DeBNXvDjJzWoPEVznfSWnozTYR8IV8mgOaUsUHE6EmMaDVp0YUJ5JQpBZQ3nkUOO9QU8+i3zq1MNP7aKHiQGpX7O6F3Milq81YP6xa+0HmdvW5TRIiX95KMj2vBrsImXkLR/tUUBW+DNg7iX8c1AjbECgYEAxzF+JeivUup/3vmOmZcmwTHHF4BacNKN7c9scnimebJA7LfgaXAeijijfaXRw/9JB0tUxfYE9NbVwCkBmnKAjIxtrIDxlMRmOz9AjakoP7EZnlgv6iSo7H+JDhlYTHu8ZUPG8XlR5SyU5kGLHkL6anx4PHL6lEbjjsxnzJKzktkCgYEAoqjsWCVtiOZlN5JZRiJFYx+MfJB8/6C/jiiEOACCqe1qxezJdAVzOKqHxXRQwv45H3VXiFnsb8x/UOy5tHQD0DFRIoM7T2x5O7cO5cf6b0JMI3wtnxhdtEbuZHZNk/LY0z6CGWCX9PScPl5iBAvv2fFyK8ZnyVajDrzblMA4OxECgYA1FhGilMK0/F4b1LKWaFwhvNxsfP6ddt/wcwlZ8KGdaU44SED8mK7q83FO+TRQYebalM8A+zIS9nZ9AfC1crKjwoEwKiU4GqeMPq07k8twPgiv1Jzgb+i9LrgeE88egxOQgWGx1T1oMFt2ih1DcWI/ovCAW7xAbCwVUJCRSr+k8QKBgQCnxzePHwZNhwdzzQbp7/mTVryd96A23iSla5DTqTf5mwrKz3zDpfIfm4LDimyCmEm3zjF/pd5t5Cdkt+yrqyWnwTlmJ0Ln2wDVz1ZHfJQ3V49yp9rkvStzDkfc/3iA+65nBzpkB/bXKaxKGjcMWcTYVjlTABqwkucZPzBSqELsxQ==" ], + "certificate" : [ "MIICuzCCAaMCBgGTTfUQazANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZSRUFMTV9OQU1FX1BMQUNFSE9MREVSMB4XDTI0MTEyMTA5MDAyNloXDTM0MTEyMTA5MDIwNlowITEfMB0GA1UEAwwWUkVBTE1fTkFNRV9QTEFDRUhPTERFUjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMPpfN0GpaH2gOnFuwfRT7LeV1j2h6VgjcMBhAzN2cZ1KPoMp8OzjRkobZ14+uN6KjQ5bU76O3u9bJSU2ihIG1KrtmXH5fwfe3F1eojFECZkq9kl2MR2Jf/bQTZy3rX6Z7cy1oGPpZH09aXgXMJOyeiufGJvpWxGYV3/xAB6gdYB+Fk2C1oV+SxM0lE0fVKGdKPw4rGqzgySBrxNkVU5EaNXCq9PTHdTSJ1miTPcg0jqfoXhccesMqpq2+bcpalMebh16N6O0RnHbbX9SFWEvIzTWkIq8bG8VkiR0ncECsbfdjbrXDtbb+Lcw76BHlSXCg6KrOjN/epOssEoA9FKDQkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAs6EEnro283f2aTTNlGYwmLThjdTynZ0f8EyTyjweJa8uzUF6zWvpAMgKgM2GVa32UpCMxydsfkn0ipsDpav1f426TBTD9wPSAtnU8nkZVX7AWtWtI6I0G3S/udKirZ2lxETSSmE5ifaO9SF1h/dEVeSJ1tr/C/YEE8ATceKgtJ7Qt8XvAgcvQuR7LCGu1HuHs2ohAvv3hjeD5Oj3HMsnLCHGHmiDW1iSxi09vkvBEDW8Hgq5/NFS/30+lnLAcA8Wx9+6zKyHWJW+f8pi6EiZgi3re8QqgJcFv/fkJjQMG9bPznfZuA+c8irLyWw6A5TLa618IqcgRZvzUyDasH4GvQ==" ], + "priority" : [ "100" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "820f56e1-92f9-489a-8d5b-435c3090d565", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "485f4929-8cd5-4823-ab43-46632ff328f1", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "7cd25178-93e4-40a1-85a3-a7eedd1eee58", + "alias" : "Browser - Conditional Organization", + "description" : "Flow to determine if the organization identity-first login is to be used", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "organization", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "13859544-1f4e-4d3a-9c59-160d72f1ef09", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "95b03f52-3e9a-4745-9f2d-fa92024f892a", + "alias" : "First Broker Login - Conditional Organization", + "description" : "Flow to determine if the authenticator that adds organization members is to be used", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "idp-add-organization-member", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "e0b0819f-f839-4ac3-93bc-a6944d789c6b", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "a39f72d5-7336-48bf-9abd-c6247d3c5188", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "d0ebe092-0fd9-4884-9df2-0fc19560cf0a", + "alias" : "Organization", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional Organization", + "userSetupAllowed" : false + } ] + }, { + "id" : "7b9d4855-89f8-4df6-beda-bfb035f9a244", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "df1575c6-b9cd-4342-8c85-c6376853866d", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "10a02bfc-f238-4b94-abbd-7706c2f21b70", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "63965b58-1b62-4f3a-9fd3-7e3e3c4c3eed", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 26, + "autheticatorFlow" : true, + "flowAlias" : "Organization", + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "618c8052-b998-4181-85f3-6e171a8ad356", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "ca3e691a-2326-450b-93d0-eb9929fc3745", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "e8c2f7fe-c611-4ef9-a062-8d6c3388f797", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "178a91fc-9bb6-43c2-88cc-5fd73afe2d75", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 50, + "autheticatorFlow" : true, + "flowAlias" : "First Broker Login - Conditional Organization", + "userSetupAllowed" : false + } ] + }, { + "id" : "4c38d67f-c298-4b46-aec8-df00f853e64a", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "ee4ae8cd-0770-44a0-89c5-de1bb96971df", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "9af610f3-08e4-4a3a-a2f2-a85c9cc65f88", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-terms-and-conditions", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 70, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "def02675-afb8-479b-9756-b6399c49a616", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "4da59173-6c48-4f89-a8f1-b9ffe3952641", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "5aab6c05-0143-49e2-a8a7-b886685e00b9", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "c00631ca-8122-41e7-bffc-6034063cc7b1", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "CONFIGURE_RECOVERY_AUTHN_CODES", + "name" : "Recovery Authentication Codes", + "providerId" : "CONFIGURE_RECOVERY_AUTHN_CODES", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "UPDATE_EMAIL", + "name" : "Update Email", + "providerId" : "UPDATE_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "VERIFY_PROFILE", + "name" : "Verify Profile", + "providerId" : "VERIFY_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 90, + "config" : { } + }, { + "alias" : "delete_credential", + "name" : "Delete Credential", + "providerId" : "delete_credential", + "enabled" : true, + "defaultAction" : false, + "priority" : 100, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "firstBrokerLoginFlow" : "first broker login", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaAuthRequestedUserHint" : "login_hint", + "clientOfflineSessionMaxLifespan" : "0", + "oauth2DevicePollingInterval" : "5", + "clientSessionIdleTimeout" : "0", + "clientOfflineSessionIdleTimeout" : "0", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false", + "cibaExpiresIn" : "120", + "oauth2DeviceCodeLifespan" : "600", + "parRequestUriLifespan" : "60", + "clientSessionMaxLifespan" : "0", + "organizationsEnabled" : "false" + }, + "keycloakVersion" : "26.0.5", + "userManagedAccessAllowed" : false, + "organizationsEnabled" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} \ No newline at end of file diff --git a/src/test/java/de/adorsys/keycloak/config/configuration/NormalizeTestConfiguration.java b/src/test/java/de/adorsys/keycloak/config/configuration/NormalizeTestConfiguration.java new file mode 100644 index 000000000..a27f1e142 --- /dev/null +++ b/src/test/java/de/adorsys/keycloak/config/configuration/NormalizeTestConfiguration.java @@ -0,0 +1,35 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.configuration; + +import de.adorsys.keycloak.config.properties.NormalizationConfigProperties; +import de.adorsys.keycloak.config.properties.NormalizationKeycloakConfigProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = {"de.adorsys.keycloak.config"}) +@EnableConfigurationProperties({NormalizationKeycloakConfigProperties.class, NormalizationConfigProperties.class}) +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE") +public class NormalizeTestConfiguration { +} diff --git a/src/test/java/de/adorsys/keycloak/config/configuration/TestConfiguration.java b/src/test/java/de/adorsys/keycloak/config/configuration/TestConfiguration.java index 27685c07a..258f4b868 100644 --- a/src/test/java/de/adorsys/keycloak/config/configuration/TestConfiguration.java +++ b/src/test/java/de/adorsys/keycloak/config/configuration/TestConfiguration.java @@ -22,6 +22,7 @@ import de.adorsys.keycloak.config.properties.ImportConfigProperties; import de.adorsys.keycloak.config.properties.KeycloakConfigProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -29,6 +30,7 @@ @Configuration @ComponentScan(basePackages = {"de.adorsys.keycloak.config"}) @EnableConfigurationProperties({KeycloakConfigProperties.class, ImportConfigProperties.class}) +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class TestConfiguration { } diff --git a/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java b/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java new file mode 100644 index 000000000..be0412dee --- /dev/null +++ b/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java @@ -0,0 +1,47 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package de.adorsys.keycloak.config.normalize; + +import de.adorsys.keycloak.config.configuration.NormalizeTestConfiguration; +import de.adorsys.keycloak.config.extensions.GithubActionsExtension; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.system.OutputCaptureExtension; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static java.util.concurrent.TimeUnit.SECONDS; + +@ExtendWith(SpringExtension.class) +@ExtendWith(GithubActionsExtension.class) +@ExtendWith(OutputCaptureExtension.class) +@ContextConfiguration( + classes = {NormalizeTestConfiguration.class}, + initializers = {ConfigDataApplicationContextInitializer.class} +) +@ActiveProfiles("normalize-IT") +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@TestClassOrder(ClassOrderer.OrderAnnotation.class) +@Timeout(value = 30, unit = SECONDS) +public abstract class AbstractNormalizeTest { +} diff --git a/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceConfigIT.java b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceConfigIT.java new file mode 100644 index 000000000..e84a02747 --- /dev/null +++ b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceConfigIT.java @@ -0,0 +1,100 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ +package de.adorsys.keycloak.config.service.normalize; + +import de.adorsys.keycloak.config.normalize.AbstractNormalizeTest; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.system.CapturedOutput; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +class AuthFlowNormalizationServiceConfigIT extends AbstractNormalizeTest { + + @Autowired + AuthFlowNormalizationService service; + + @Test + public void testNormalizeAuthConfigsWithEmptyListsIsNull() { + var resultingAuthConfig = service.normalizeAuthConfig(new ArrayList<>(), new ArrayList<>()); + Assertions.assertThat(resultingAuthConfig).isNull(); + } + + @Test + public void testNormalizeAuthConfigsAreRemovedWithoutAliasReference(CapturedOutput output) { + AuthenticatorConfigRepresentation authenticatorConfigRepresentation = new AuthenticatorConfigRepresentation(); + authenticatorConfigRepresentation.setAlias("config2"); + + AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation(); + + AuthenticationExecutionExportRepresentation authenticationExecutionExportRepresentation = new AuthenticationExecutionExportRepresentation(); + authenticationExecutionExportRepresentation.setAuthenticatorConfig("config1"); + authenticationFlowRepresentation.setAuthenticationExecutions(List.of(authenticationExecutionExportRepresentation)); + + var resultingAuthConfig = service.normalizeAuthConfig(List.of(authenticatorConfigRepresentation), List.of(authenticationFlowRepresentation)); + + Assertions.assertThat(resultingAuthConfig).isNull(); + Assertions.assertThat(output.getOut()).contains("Some authenticator configs are unused."); + } + + @Test + public void testNormalizeAuthConfigsRemainWithAliasReference() { + AuthenticatorConfigRepresentation authenticatorConfigRepresentation = new AuthenticatorConfigRepresentation(); + authenticatorConfigRepresentation.setAlias("config1"); + + AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation(); + + AuthenticationExecutionExportRepresentation authenticationExecutionExportRepresentation = new AuthenticationExecutionExportRepresentation(); + authenticationExecutionExportRepresentation.setAuthenticatorConfig("config1"); + authenticationFlowRepresentation.setAuthenticationExecutions(List.of(authenticationExecutionExportRepresentation)); + + var resultingAuthConfig = service.normalizeAuthConfig(List.of(authenticatorConfigRepresentation), List.of(authenticationFlowRepresentation)); + + Assertions.assertThat(resultingAuthConfig).containsExactlyInAnyOrder(authenticatorConfigRepresentation); + } + + @Test + public void testNormalizeAuthConfigsCheckedForDuplicates(CapturedOutput output) { + AuthenticatorConfigRepresentation authenticatorConfigRepresentation1 = new AuthenticatorConfigRepresentation(); + authenticatorConfigRepresentation1.setId(UUID.randomUUID().toString()); + authenticatorConfigRepresentation1.setAlias("config1"); + + AuthenticatorConfigRepresentation authenticatorConfigRepresentation2 = new AuthenticatorConfigRepresentation(); + authenticatorConfigRepresentation2.setId(UUID.randomUUID().toString()); + authenticatorConfigRepresentation2.setAlias("config1"); + + AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation(); + + AuthenticationExecutionExportRepresentation authenticationExecutionExportRepresentation = new AuthenticationExecutionExportRepresentation(); + authenticationExecutionExportRepresentation.setAuthenticatorConfig("config1"); + authenticationFlowRepresentation.setAuthenticationExecutions(List.of(authenticationExecutionExportRepresentation)); + + var resultingAuthConfig = service.normalizeAuthConfig(List.of(authenticatorConfigRepresentation1, authenticatorConfigRepresentation2), List.of(authenticationFlowRepresentation)); + + Assertions.assertThat(resultingAuthConfig).containsExactlyInAnyOrder(authenticatorConfigRepresentation1, authenticatorConfigRepresentation2); + Assertions.assertThat(output.getOut()).contains("The following authenticator configs are duplicates: [config1]"); + } +} diff --git a/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceFlowIT.java b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceFlowIT.java new file mode 100644 index 000000000..9cf67c2dd --- /dev/null +++ b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceFlowIT.java @@ -0,0 +1,72 @@ +/*- + * ---license-start + * keycloak-config-cli + * --- + * Copyright (C) 2017 - 2021 adorsys GmbH & Co. KG @ https://adorsys.com + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ +package de.adorsys.keycloak.config.service.normalize; + +import de.adorsys.keycloak.config.normalize.AbstractNormalizeTest; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.system.CapturedOutput; + +import java.util.ArrayList; +import java.util.List; + +class AuthFlowNormalizationServiceFlowIT extends AbstractNormalizeTest { + + @Autowired + AuthFlowNormalizationService service; + + + @Test + public void testNormalizeAuthFlows() { + var resultingAuthFlows = service.normalizeAuthFlows(new ArrayList<>(), new ArrayList<>()); + Assertions.assertThat(resultingAuthFlows).isNull(); + } + + @Test + public void testNormalizeAuthFlowsIgnoreBuiltInTrue() { + AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation(); + authenticationFlowRepresentation.setBuiltIn(true); + + AuthenticationFlowRepresentation authenticationFlowRepresentationBaseline = new AuthenticationFlowRepresentation(); + authenticationFlowRepresentationBaseline.setBuiltIn(true); + + var resultingAuthFlows = service.normalizeAuthFlows(List.of(authenticationFlowRepresentation), List.of(authenticationFlowRepresentationBaseline)); + + Assertions.assertThat(resultingAuthFlows).isNull(); + } + + @Test + public void testNormalizeAuthFlowsIgnoreBuiltInTrueButBaselineHasEntryCreatesRecreationWarning(CapturedOutput output) { + AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation(); + authenticationFlowRepresentation.setBuiltIn(true); + + AuthenticationFlowRepresentation authenticationFlowRepresentationBaseline = new AuthenticationFlowRepresentation(); + authenticationFlowRepresentationBaseline.setBuiltIn(false); + authenticationFlowRepresentationBaseline.setAlias("flow1"); + + var resultingAuthFlows = service.normalizeAuthFlows(List.of(authenticationFlowRepresentation), List.of(authenticationFlowRepresentationBaseline)); + + Assertions.assertThat(resultingAuthFlows).isNull(); + Assertions.assertThat(output.getOut()).contains("Default realm authentication flow 'flow1' was deleted in exported realm. It may be reintroduced during import"); + + } +} diff --git a/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakAuthentication.java b/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakAuthentication.java index fc51a9c29..0fd695d1b 100644 --- a/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakAuthentication.java +++ b/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakAuthentication.java @@ -24,9 +24,11 @@ import org.keycloak.admin.client.Keycloak; import org.keycloak.representations.AccessTokenResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class KeycloakAuthentication { private final KeycloakConfigProperties keycloakConfigProperties; diff --git a/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java b/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java index 4e4c15260..4e5da67fa 100644 --- a/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java +++ b/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java @@ -24,6 +24,7 @@ import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import java.util.List; @@ -34,6 +35,7 @@ import static org.hamcrest.Matchers.hasSize; @Component +@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "IMPORT", matchIfMissing = true) public class KeycloakRepository { private final KeycloakProvider keycloakProvider; diff --git a/src/test/resources/application-normalize-IT.properties b/src/test/resources/application-normalize-IT.properties new file mode 100644 index 000000000..77a36297e --- /dev/null +++ b/src/test/resources/application-normalize-IT.properties @@ -0,0 +1,3 @@ +run.operation=normalize +normalization.files.input-locations=default +normalization.files.output-directory=default-output diff --git a/src/test/resources/import-files/exported-realm/25.0.1/master-realm.json b/src/test/resources/import-files/exported-realm/25.0.1/master-realm.json index 0b3fba793..6856d9e6c 100644 --- a/src/test/resources/import-files/exported-realm/25.0.1/master-realm.json +++ b/src/test/resources/import-files/exported-realm/25.0.1/master-realm.json @@ -1,5 +1,5 @@ { - "id" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3", + "id" : "6219f172-5cbc-40f1-99fc-74218bbb2642", "realm" : "master", "displayName" : "Keycloak", "displayNameHtml" : "
Keycloak
", @@ -48,56 +48,56 @@ "failureFactor" : 30, "roles" : { "realm" : [ { - "id" : "53a94a55-01b7-4ac3-97a1-1df924dfcf05", - "name" : "admin", - "description" : "${role_admin}", - "composite" : true, - "composites" : { - "realm" : [ "create-realm" ], - "client" : { - "master-realm" : [ "view-identity-providers", "manage-realm", "view-authorization", "query-realms", "manage-users", "query-groups", "manage-events", "impersonation", "create-client", "view-users", "manage-authorization", "manage-clients", "manage-identity-providers", "view-events", "query-clients", "view-realm", "query-users", "view-clients" ] - } - }, + "id" : "6adf69e5-3f69-4ae0-b2f9-6bf3663f10df", + "name" : "create-realm", + "description" : "${role_create-realm}", + "composite" : false, "clientRole" : false, - "containerId" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3", + "containerId" : "6219f172-5cbc-40f1-99fc-74218bbb2642", "attributes" : { } }, { - "id" : "1d93addd-604f-4388-bff2-48849ce0317c", - "name" : "default-roles-master", - "description" : "${role_default-roles}", + "id" : "bb03f721-bd79-4a61-97a5-963ed89fffc2", + "name" : "admin", + "description" : "${role_admin}", "composite" : true, "composites" : { - "realm" : [ "offline_access", "uma_authorization" ], + "realm" : [ "create-realm" ], "client" : { - "account" : [ "manage-account", "view-profile" ] + "master-realm" : [ "view-realm", "query-groups", "view-identity-providers", "view-users", "manage-clients", "impersonation", "view-events", "view-authorization", "create-client", "manage-identity-providers", "query-users", "manage-events", "manage-realm", "view-clients", "query-clients", "manage-users", "query-realms", "manage-authorization" ] } }, "clientRole" : false, - "containerId" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3", + "containerId" : "6219f172-5cbc-40f1-99fc-74218bbb2642", "attributes" : { } }, { - "id" : "9b065c78-db9e-4183-b94c-32e4e938e753", + "id" : "a679e5c1-976e-48bf-9082-02d743a9e589", "name" : "uma_authorization", "description" : "${role_uma_authorization}", "composite" : false, "clientRole" : false, - "containerId" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3", + "containerId" : "6219f172-5cbc-40f1-99fc-74218bbb2642", "attributes" : { } }, { - "id" : "98701e4d-2cb1-4916-b6c1-3a1e5fa8b98f", - "name" : "create-realm", - "description" : "${role_create-realm}", + "id" : "ac87814d-ff14-4e9d-8868-b266c437e6d6", + "name" : "offline_access", + "description" : "${role_offline-access}", "composite" : false, "clientRole" : false, - "containerId" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3", + "containerId" : "6219f172-5cbc-40f1-99fc-74218bbb2642", "attributes" : { } }, { - "id" : "868a6403-4176-49bf-a0e7-57f97f738a93", - "name" : "offline_access", - "description" : "${role_offline-access}", - "composite" : false, + "id" : "0de3d9a9-ce18-4638-806f-a96e61e93e62", + "name" : "default-roles-master", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "view-profile", "manage-account" ] + } + }, "clientRole" : false, - "containerId" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3", + "containerId" : "6219f172-5cbc-40f1-99fc-74218bbb2642", "attributes" : { } } ], "client" : { @@ -105,254 +105,254 @@ "admin-cli" : [ ], "account-console" : [ ], "broker" : [ { - "id" : "a6139113-e9c8-4343-9de3-3a46d4c4efe7", + "id" : "79f6152f-2a01-49de-9bda-217c8dc37ed9", "name" : "read-token", "description" : "${role_read-token}", "composite" : false, "clientRole" : true, - "containerId" : "6b259285-42b1-430f-b619-b83ca1b86e14", + "containerId" : "7000b14a-6262-498a-a2f5-244e4678377b", "attributes" : { } } ], "master-realm" : [ { - "id" : "a163010b-6b99-4f2e-abe3-7f36ba5f5216", - "name" : "manage-realm", - "description" : "${role_manage-realm}", + "id" : "c392c688-47d7-437b-adec-22136507b23f", + "name" : "view-realm", + "description" : "${role_view-realm}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "2c6efea3-2979-45e8-b10a-b95ececa0a25", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", + "id" : "67373ba8-2fef-486f-a073-f70fe6ff2d40", + "name" : "query-groups", + "description" : "${role_query-groups}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "e978f2e8-76ed-45cf-a23e-66ee5cbc95b8", - "name" : "view-authorization", - "description" : "${role_view-authorization}", + "id" : "ceb4d197-4bcc-47e8-8a01-23cdbf866d99", + "name" : "manage-clients", + "description" : "${role_manage-clients}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "b548358b-4380-4e03-bb26-06b3411b19ad", - "name" : "query-realms", - "description" : "${role_query-realms}", + "id" : "1cbe7eae-2531-4886-8e15-4ebcb64f4d6a", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "9cb299ae-2994-4d56-afab-1de48dcceb40", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, + "id" : "7f84085d-61a9-48ea-9413-f1a6cf624de3", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "master-realm" : [ "query-users", "query-groups" ] + } + }, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "97eb77cd-1b31-4c65-a259-e223625d3f57", - "name" : "query-groups", - "description" : "${role_query-groups}", + "id" : "90844634-3048-4978-9627-850fd860cff9", + "name" : "impersonation", + "description" : "${role_impersonation}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "87209a50-c857-4c25-927c-e99894473644", - "name" : "manage-events", - "description" : "${role_manage-events}", + "id" : "c3f0eca1-d6f3-444e-af5f-f5d06aae2109", + "name" : "view-events", + "description" : "${role_view-events}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "2cc052ac-aa7f-4b7f-a214-90970e1796fd", - "name" : "impersonation", - "description" : "${role_impersonation}", + "id" : "25add48d-8b05-4e38-a186-1b87bb6e41d8", + "name" : "view-authorization", + "description" : "${role_view-authorization}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "3346327d-b28e-4953-8221-f2df72921c57", + "id" : "f4982c2e-16eb-4952-a89d-baedccef43ee", "name" : "create-client", "description" : "${role_create-client}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "c1acb6df-0a73-4c25-a60c-ef3056402f0c", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-groups", "query-users" ] - } - }, + "id" : "f86aba84-f00c-4e7f-b61a-69b904407054", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "63b51825-4b31-4202-aa8d-3bcff3a32e81", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", + "id" : "af9bd51e-4ea8-4f76-a6e4-24a3c185199a", + "name" : "query-users", + "description" : "${role_query-users}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "972d72c4-1f32-4820-88c8-cecca886f210", - "name" : "manage-clients", - "description" : "${role_manage-clients}", + "id" : "f5f10511-8bb2-42c0-9c29-e65704de7975", + "name" : "manage-events", + "description" : "${role_manage-events}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "a859851a-ad17-44f8-a166-976a7f747dc9", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", + "id" : "639eb9ed-6a64-4c39-9fbb-62eab53f8757", + "name" : "manage-realm", + "description" : "${role_manage-realm}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "ae843368-1257-444d-8bd9-5e7bca083c9c", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, + "id" : "6528f9b3-441b-4804-a1ce-e49800180828", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "master-realm" : [ "query-clients" ] + } + }, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "54aeb96f-1659-44d0-b04a-8b6b4a366b86", + "id" : "8806c16d-f477-4961-822f-84a85943d1a5", "name" : "query-clients", "description" : "${role_query-clients}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "4005abb7-7e93-4d21-abd6-2831ac384d38", - "name" : "view-realm", - "description" : "${role_view-realm}", + "id" : "d49309b7-e9db-44d1-bb2a-9400749b2cba", + "name" : "manage-users", + "description" : "${role_manage-users}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "119041e5-873f-4e61-a507-8e34e4a29c83", - "name" : "query-users", - "description" : "${role_query-users}", + "id" : "b248d6b9-88a9-446c-b342-cffa0c0e1c68", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } }, { - "id" : "6582bf22-fb94-4c3d-9269-3ba600b6a3a1", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-clients" ] - } - }, + "id" : "649be7d5-0867-4239-823e-1a52009723a0", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, "clientRole" : true, - "containerId" : "01702696-84f2-4815-9385-493495f5542e", + "containerId" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "attributes" : { } } ], "account" : [ { - "id" : "5319ddd7-6971-4022-b43a-30ee6029d25d", - "name" : "manage-consent", - "description" : "${role_manage-consent}", + "id" : "00f89d17-5a26-43b4-978d-0bdf53aff4c2", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", + "attributes" : { } + }, { + "id" : "4bef4c6e-b8b4-48b5-9da9-6997e5b1c736", + "name" : "manage-account", + "description" : "${role_manage-account}", "composite" : true, "composites" : { "client" : { - "account" : [ "view-consent" ] + "account" : [ "manage-account-links" ] } }, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } }, { - "id" : "8a61a541-f46c-406a-8d50-0dcd3821ad19", - "name" : "manage-account", - "description" : "${role_manage-account}", + "id" : "4ee3ca7d-80d3-48a9-8abc-a81810f8a54d", + "name" : "manage-consent", + "description" : "${role_manage-consent}", "composite" : true, "composites" : { "client" : { - "account" : [ "manage-account-links" ] + "account" : [ "view-consent" ] } }, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } }, { - "id" : "91b1cb2f-7fba-40e5-9988-b43d4ebb25d9", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", + "id" : "b9b776b4-6b04-469f-ab21-5afb25b1c77d", + "name" : "delete-account", + "description" : "${role_delete-account}", "composite" : false, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } }, { - "id" : "18cdd8ee-f35c-40e6-a09a-5743388b6f18", + "id" : "c827cdf1-85c9-4e89-a71e-dff5bd5efb3d", "name" : "view-applications", "description" : "${role_view-applications}", "composite" : false, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } }, { - "id" : "346078cb-e7e0-45f8-b738-1bf58b02251d", - "name" : "view-profile", - "description" : "${role_view-profile}", + "id" : "8517234d-dc7e-4902-b51b-d1e4084388dd", + "name" : "view-groups", + "description" : "${role_view-groups}", "composite" : false, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } }, { - "id" : "518fb059-94bd-4b76-96b4-8c08381ceab8", - "name" : "delete-account", - "description" : "${role_delete-account}", + "id" : "558181c3-87d7-4e45-a4bf-f794c2fec2bb", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", "composite" : false, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } }, { - "id" : "7d8f33e0-f53a-4d5a-9e0d-422a245cb236", + "id" : "fd7dd764-fc90-41da-8d03-dac55062f432", "name" : "view-consent", "description" : "${role_view-consent}", "composite" : false, "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", - "attributes" : { } - }, { - "id" : "717fdfe3-4d46-4d23-8248-5b06b73a5d26", - "name" : "view-groups", - "description" : "${role_view-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "containerId" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "attributes" : { } } ] } }, "groups" : [ ], "defaultRole" : { - "id" : "1d93addd-604f-4388-bff2-48849ce0317c", + "id" : "0de3d9a9-ce18-4638-806f-a96e61e93e62", "name" : "default-roles-master", "description" : "${role_default-roles}", "composite" : true, "clientRole" : false, - "containerId" : "758ff4fc-bf09-403b-adbe-c9a56cadd5d3" + "containerId" : "6219f172-5cbc-40f1-99fc-74218bbb2642" }, "requiredCredentials" : [ "password" ], "otpPolicyType" : "totp", @@ -397,7 +397,7 @@ } ] }, "clients" : [ { - "id" : "3dca789b-ddb0-4882-9dc3-9162dbce1a34", + "id" : "0db272fc-6ba8-45fc-b64a-ec0f21ab60c7", "clientId" : "account", "name" : "${client_account}", "rootUrl" : "${authBaseUrl}", @@ -424,10 +424,10 @@ "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] }, { - "id" : "fcc26741-1267-44df-880c-0db1273037db", + "id" : "4b5a85e3-b814-4490-a08f-450411a65f38", "clientId" : "account-console", "name" : "${client_account-console}", "rootUrl" : "${authBaseUrl}", @@ -456,17 +456,17 @@ "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, "protocolMappers" : [ { - "id" : "5f785b3b-9c2f-40d6-a090-2391dec074c5", + "id" : "cff0218a-6481-4a33-9a1d-35ffe3b9b532", "name" : "audience resolve", "protocol" : "openid-connect", "protocolMapper" : "oidc-audience-resolve-mapper", "consentRequired" : false, "config" : { } } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] }, { - "id" : "eca9e50a-1405-4a18-ba60-50079856d282", + "id" : "ba46734c-078a-45a4-9ab6-6462abee8aca", "clientId" : "admin-cli", "name" : "${client_admin-cli}", "surrogateAuthRequired" : false, @@ -489,10 +489,10 @@ "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] }, { - "id" : "6b259285-42b1-430f-b619-b83ca1b86e14", + "id" : "7000b14a-6262-498a-a2f5-244e4678377b", "clientId" : "broker", "name" : "${client_broker}", "surrogateAuthRequired" : false, @@ -515,10 +515,10 @@ "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] }, { - "id" : "01702696-84f2-4815-9385-493495f5542e", + "id" : "4d54a69f-edc0-40da-a0e1-5a8f136913e6", "clientId" : "master-realm", "name" : "master Realm", "surrogateAuthRequired" : false, @@ -540,10 +540,10 @@ "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] }, { - "id" : "6a9e0ce9-0ceb-4bf4-9c12-245996c2d202", + "id" : "cd6fc819-1bd0-4173-974a-cee8ad45e24b", "clientId" : "security-admin-console", "name" : "${client_security-admin-console}", "rootUrl" : "${authAdminUrl}", @@ -572,7 +572,7 @@ "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, "protocolMappers" : [ { - "id" : "686aee26-100e-40f9-bff6-f09f38a48f17", + "id" : "5dd33aa0-3f10-4d21-a911-9849fd1d51c8", "name" : "locale", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", @@ -587,182 +587,214 @@ "jsonType.label" : "String" } } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] } ], "clientScopes" : [ { - "id" : "899b0c35-7ed6-4898-a421-a7472af73c2f", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", + "id" : "aae7ae1c-e7b8-44a1-8b7c-a0b1784025af", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", "protocol" : "openid-connect", "attributes" : { - "include.in.token.scope" : "true", - "consent.screen.text" : "${emailScopeConsentText}", + "include.in.token.scope" : "false", + "consent.screen.text" : "${rolesScopeConsentText}", "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "a2122fd7-8d95-4221-8928-0681c1403d30", - "name" : "email", + "id" : "a4387c51-3ae8-4afc-856b-fc7779bd4684", + "name" : "audience resolve", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", + "protocolMapper" : "oidc-audience-resolve-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "email", - "id.token.claim" : "true", + "access.token.claim" : "true" + } + }, { + "id" : "ebe74b14-fcf7-401d-94dd-493344976566", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "email", - "jsonType.label" : "String" + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" } }, { - "id" : "f8a0e045-fb36-4a13-8c2e-34831232676a", - "name" : "email verified", + "id" : "23becefb-f723-45f8-a10b-8bd038464259", + "name" : "client roles", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", + "protocolMapper" : "oidc-usermodel-client-role-mapper", "consentRequired" : false, "config" : { + "user.attribute" : "foo", "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", - "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "email_verified", - "jsonType.label" : "boolean" + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" } } ] }, { - "id" : "26251e40-1e68-4e9f-a09d-8e974d8a0f83", - "name" : "profile", - "description" : "OpenID Connect built-in scope: profile", + "id" : "1374660d-88db-4973-b069-4bca7ff7fcaa", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "true", - "consent.screen.text" : "${profileScopeConsentText}", + "consent.screen.text" : "${addressScopeConsentText}", "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "3546bbbe-28dc-4d24-98fe-25b6d976bba7", - "name" : "birthdate", + "id" : "dc13ff65-fdb1-433c-864a-e9e417a020ef", + "name" : "address", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", + "protocolMapper" : "oidc-address-mapper", "consentRequired" : false, "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", + "user.attribute.street" : "street", "id.token.claim" : "true", + "user.attribute.region" : "region", "access.token.claim" : "true", - "claim.name" : "birthdate", - "jsonType.label" : "String" + "user.attribute.locality" : "locality" } - }, { - "id" : "cea32932-d177-4a97-bf90-2470c7cea25c", - "name" : "updated at", + } ] + }, { + "id" : "2f39e5ff-3645-42de-bfbd-61c5e9e97444", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "5613edc2-0440-4b67-a2cf-4fa42de6edd6", + "name" : "groups", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", + "multivalued" : "true", + "user.attribute" : "foo", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "long" + "claim.name" : "groups", + "jsonType.label" : "String" } }, { - "id" : "715e18d7-6065-4d3e-84e9-e0e132abac95", - "name" : "website", + "id" : "aed0d46f-b959-44d9-b816-277adb346924", + "name" : "upn", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "website", + "user.attribute" : "username", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "website", + "claim.name" : "upn", "jsonType.label" : "String" } - }, { - "id" : "e75bbc3d-af42-401c-874f-52a4f93cc87e", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", + } ] + }, { + "id" : "c5f49220-a07e-44aa-a0a3-938a935fa84a", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${profileScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "79aba687-365d-4a32-9993-085e17be0357", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "locale", + "user.attribute" : "firstName", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "locale", + "claim.name" : "given_name", "jsonType.label" : "String" } }, { - "id" : "85a3678d-781f-4720-abc7-b7644d00c190", - "name" : "given name", + "id" : "e357d5ad-aaac-4763-b30a-0483e21fe170", + "name" : "username", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "firstName", + "user.attribute" : "username", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "given_name", + "claim.name" : "preferred_username", "jsonType.label" : "String" } }, { - "id" : "2cf08e4b-96c9-4d1c-8dda-972fcb31ddc1", - "name" : "family name", + "id" : "4978de55-9d4c-44ef-b090-60cfe0107094", + "name" : "updated at", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "lastName", + "user.attribute" : "updatedAt", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "family_name", - "jsonType.label" : "String" + "claim.name" : "updated_at", + "jsonType.label" : "long" } }, { - "id" : "3ffa4a0a-b80f-49ca-af51-1914071f38cb", - "name" : "username", + "id" : "a068f777-29aa-498d-8bd5-114e3324463a", + "name" : "website", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "username", + "user.attribute" : "website", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "preferred_username", + "claim.name" : "website", "jsonType.label" : "String" } }, { - "id" : "313e8b54-2446-4279-a2b0-1d0436ecd83b", - "name" : "middle name", + "id" : "70882b82-8ac2-4014-926b-900e2b5dea9a", + "name" : "profile", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "middleName", + "user.attribute" : "profile", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "middle_name", + "claim.name" : "profile", "jsonType.label" : "String" } }, { - "id" : "92e5dbd5-f2ab-42d7-a297-4c1fcf3b4fb5", + "id" : "c3817b85-b874-4fef-8aa3-551df9fd82bf", "name" : "full name", "protocol" : "openid-connect", "protocolMapper" : "oidc-full-name-mapper", @@ -774,22 +806,22 @@ "userinfo.token.claim" : "true" } }, { - "id" : "888ae77e-149f-4e61-9b57-b977df391261", - "name" : "picture", + "id" : "91b49f55-c0da-4bc4-a011-07239c9af877", + "name" : "middle name", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "picture", + "user.attribute" : "middleName", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "picture", + "claim.name" : "middle_name", "jsonType.label" : "String" } }, { - "id" : "8d9a48f6-9891-4096-b154-5ff53e4a92fb", + "id" : "a0c47ed4-638a-4249-af90-2ac1d041ba8f", "name" : "gender", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", @@ -804,96 +836,98 @@ "jsonType.label" : "String" } }, { - "id" : "8d465f23-2d9d-4eba-89ef-beea34735658", - "name" : "nickname", + "id" : "5e321f9d-2580-44b4-9b6e-8c06518235a6", + "name" : "zoneinfo", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "nickname", + "user.attribute" : "zoneinfo", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "nickname", + "claim.name" : "zoneinfo", "jsonType.label" : "String" } }, { - "id" : "846fc3d1-6e0d-47fc-ab57-bba15b77c8be", - "name" : "profile", + "id" : "ce6c6755-9351-4a3f-ac73-efc071ef225a", + "name" : "locale", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "profile", + "user.attribute" : "locale", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "profile", + "claim.name" : "locale", "jsonType.label" : "String" } }, { - "id" : "9665ff98-2323-4d76-8c68-af8fbc0b049a", - "name" : "zoneinfo", + "id" : "302b2116-26fe-4b51-bf38-b43942e08afe", + "name" : "birthdate", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", + "user.attribute" : "birthdate", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "zoneinfo", + "claim.name" : "birthdate", "jsonType.label" : "String" } - } ] - }, { - "id" : "5da42d73-cd9c-4867-9aa2-92074e8f8ab4", - "name" : "basic", - "description" : "OpenID Connect scope for add all basic claims to the token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "65e5ca75-9ad9-4ed9-b69b-aa71967d8a63", - "name" : "sub", + }, { + "id" : "92438586-bc3e-48e9-a4c5-ca16b7970be0", + "name" : "family name", "protocol" : "openid-connect", - "protocolMapper" : "oidc-sub-mapper", + "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", - "access.token.claim" : "true" + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" } }, { - "id" : "acc79e05-b344-43b3-918b-2832585bde15", - "name" : "auth_time", + "id" : "8c61c413-c9f2-4c11-8764-930d9941b5ae", + "name" : "nickname", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { - "user.session.note" : "AUTH_TIME", + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "491ee6ac-8ef2-48bc-b246-e55c37f59add", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "auth_time", - "jsonType.label" : "long" + "claim.name" : "picture", + "jsonType.label" : "String" } } ] }, { - "id" : "320b51af-0c74-4d71-b6f4-dc262b4297f9", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } - }, { - "id" : "84bb2402-4693-4078-9cf0-8d8fa2d09408", + "id" : "85a4c487-8c44-4f76-b410-4a27c4083f47", "name" : "phone", "description" : "OpenID Connect built-in scope: phone", "protocol" : "openid-connect", @@ -903,7 +937,7 @@ "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "b5f014fb-0ab0-48cf-a676-8e1c5dadef0b", + "id" : "d6b080b8-3d56-4e43-acb1-3c1b070fe8af", "name" : "phone number", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", @@ -918,7 +952,7 @@ "jsonType.label" : "String" } }, { - "id" : "bf410999-86a7-49a6-9c3c-05fc8cb83605", + "id" : "cfecf6e0-9e79-4436-9d39-ed55e900a67e", "name" : "phone number verified", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", @@ -934,167 +968,112 @@ } } ] }, { - "id" : "ab92a399-0b8b-4821-96a9-feafef914549", - "name" : "acr", - "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "id" : "bd1afe0e-1af8-4cba-bc93-c77b558d9067", + "name" : "basic", + "description" : "OpenID Connect scope for add all basic claims to the token", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "false", "display.on.consent.screen" : "false" }, "protocolMappers" : [ { - "id" : "2b06dd12-3493-4f63-8878-0d847514e641", - "name" : "acr loa level", + "id" : "42df3f15-5f54-4b88-9541-bcde05766379", + "name" : "auth_time", "protocol" : "openid-connect", - "protocolMapper" : "oidc-acr-mapper", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", "consentRequired" : false, "config" : { + "user.session.note" : "AUTH_TIME", "id.token.claim" : "true", "introspection.token.claim" : "true", - "access.token.claim" : "true" + "access.token.claim" : "true", + "claim.name" : "auth_time", + "jsonType.label" : "long" } - } ] - }, { - "id" : "46dd6349-36e6-476b-9dbf-180bc8a31b83", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "consent.screen.text" : "${addressScopeConsentText}", - "display.on.consent.screen" : "true" - }, - "protocolMappers" : [ { - "id" : "711afd99-66ea-43df-8275-199b0900ca1a", - "name" : "address", + }, { + "id" : "9186563e-5761-4c48-bd15-1f59e51c882a", + "name" : "sub", "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", + "protocolMapper" : "oidc-sub-mapper", "consentRequired" : false, "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", "introspection.token.claim" : "true", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" + "access.token.claim" : "true" } } ] }, { - "id" : "e87b9d27-b432-4459-ab13-e7c035625bed", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", + "id" : "10faa820-bd35-47f6-97b3-dd2820c4e9e9", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", "protocol" : "openid-connect", "attributes" : { - "include.in.token.scope" : "true", + "include.in.token.scope" : "false", "display.on.consent.screen" : "false" }, "protocolMappers" : [ { - "id" : "a68090d0-c1f7-48e1-9f32-5d2ec77457d8", - "name" : "groups", + "id" : "bfef859b-30ac-49ad-88dd-fe43425c0290", + "name" : "acr loa level", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "protocolMapper" : "oidc-acr-mapper", "consentRequired" : false, "config" : { - "introspection.token.claim" : "true", - "multivalued" : "true", - "user.attribute" : "foo", "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" - } - }, { - "id" : "2b4f0429-6464-4ff7-b514-742fd9406bd0", - "name" : "upn", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "upn", - "jsonType.label" : "String" + "access.token.claim" : "true" } } ] }, { - "id" : "a4d66eac-66c9-40e7-9c0e-2de645c4a415", - "name" : "role_list", - "description" : "SAML role list", - "protocol" : "saml", + "id" : "003d13b6-5b72-4f7b-add9-dab6330ec555", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", "attributes" : { - "consent.screen.text" : "${samlRoleListScopeConsentText}", + "consent.screen.text" : "${offlineAccessScopeConsentText}", "display.on.consent.screen" : "true" - }, - "protocolMappers" : [ { - "id" : "6148e600-1a63-4caa-946a-efe35d0a3bb4", - "name" : "role list", - "protocol" : "saml", - "protocolMapper" : "saml-role-list-mapper", - "consentRequired" : false, - "config" : { - "single" : "false", - "attribute.nameformat" : "Basic", - "attribute.name" : "Role" - } - } ] + } }, { - "id" : "8f865f22-1e06-4426-a2af-1e3b683c6450", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", + "id" : "9f4285c8-31e0-4339-ae6c-7eb9725da69b", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", "protocol" : "openid-connect", "attributes" : { - "include.in.token.scope" : "false", - "consent.screen.text" : "${rolesScopeConsentText}", + "include.in.token.scope" : "true", + "consent.screen.text" : "${emailScopeConsentText}", "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "b1dc3cca-f0bd-45c2-a52d-f9aef46deebe", - "name" : "realm roles", + "id" : "651f856b-739f-4797-b32c-49a9f571223e", + "name" : "email", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { - "user.attribute" : "foo", "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String", - "multivalued" : "true" + "claim.name" : "email", + "jsonType.label" : "String" } }, { - "id" : "8c5de524-3ba5-4f03-9f8f-a0f45e48df6b", - "name" : "client roles", + "id" : "d8e18659-6fdc-4c40-a65e-4d855f514cf9", + "name" : "email verified", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", + "protocolMapper" : "oidc-usermodel-property-mapper", "consentRequired" : false, "config" : { - "user.attribute" : "foo", "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "e8786aa2-884c-40e0-b276-eb7fbd855791", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "access.token.claim" : "true" + "claim.name" : "email_verified", + "jsonType.label" : "boolean" } } ] }, { - "id" : "f1a9e164-cb83-4b91-ac53-7dfe3f6729a6", + "id" : "5139ea54-1669-4a7d-980e-e8a9d7a83d57", "name" : "web-origins", "description" : "OpenID Connect scope for add allowed web origins to the access token", "protocol" : "openid-connect", @@ -1104,7 +1083,7 @@ "display.on.consent.screen" : "false" }, "protocolMappers" : [ { - "id" : "18d62bcd-170e-47c7-93ae-4072f19a1853", + "id" : "febb8ed8-fc30-4d3b-8cc0-729718b3ea7a", "name" : "allowed web origins", "protocol" : "openid-connect", "protocolMapper" : "oidc-allowed-origins-mapper", @@ -1114,6 +1093,27 @@ "access.token.claim" : "true" } } ] + }, { + "id" : "4f6e34b8-158a-4e79-9673-4bc54d984ee0", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "cb55abfc-fda7-4c0e-9b04-fe3059b2b021", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] } ], "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr", "basic" ], "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], @@ -1137,57 +1137,60 @@ "identityProviderMappers" : [ ], "components" : { "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "e76aa8ea-4198-41dd-b498-9951d1459df4", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", + "id" : "00642647-1062-4330-8624-4be0a926d7be", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-address-mapper" ] + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] } }, { - "id" : "fa3f9cf0-c53a-48bb-adb8-f27f66e3568e", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", + "id" : "7ab2c08b-901f-4b95-b303-1fa87fab5034", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", "subComponents" : { }, - "config" : { } + "config" : { + "allow-default-scopes" : [ "true" ] + } }, { - "id" : "10077ff3-12ce-40d5-9108-2de23a14d541", - "name" : "Consent Required", - "providerId" : "consent-required", + "id" : "a1ac08b2-1946-4610-854e-7b301164b98b", + "name" : "Max Clients Limit", + "providerId" : "max-clients", "subType" : "anonymous", "subComponents" : { }, - "config" : { } + "config" : { + "max-clients" : [ "200" ] + } }, { - "id" : "fb43aaf7-481b-462c-9cd3-062d44a42492", + "id" : "75084497-05b2-4978-8088-fe920f5e165e", "name" : "Allowed Protocol Mapper Types", "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", + "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper" ] + "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper" ] } }, { - "id" : "b92ef2e1-c333-4daf-80b2-b0dc016bb613", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "authenticated", + "id" : "cd373617-6545-43f2-954a-035b08da1d4b", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", "subComponents" : { }, "config" : { - "allow-default-scopes" : [ "true" ] + "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper" ] } }, { - "id" : "dae5ff77-754e-4b08-ae16-18e2105a20a8", - "name" : "Max Clients Limit", - "providerId" : "max-clients", + "id" : "843e6e4b-caa8-42ed-bbb2-be158983514e", + "name" : "Consent Required", + "providerId" : "consent-required", "subType" : "anonymous", "subComponents" : { }, - "config" : { - "max-clients" : [ "200" ] - } + "config" : { } }, { - "id" : "7cfe8082-e7b6-4fe2-805f-4bab1c80f66b", + "id" : "bb925f89-8bd3-44cd-942a-d2615fda21f6", "name" : "Allowed Client Scopes", "providerId" : "allowed-client-templates", "subType" : "anonymous", @@ -1196,18 +1199,15 @@ "allow-default-scopes" : [ "true" ] } }, { - "id" : "a0aa3cab-ce51-4f90-af7d-22a8a4d425e0", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", + "id" : "d8d6abb4-2ea7-4a13-b325-f7bf359b929a", + "name" : "Full Scope Disabled", + "providerId" : "scope", "subType" : "anonymous", "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } + "config" : { } } ], "org.keycloak.userprofile.UserProfileProvider" : [ { - "id" : "9adea1fb-e00d-4b4d-80dc-49ad060e17b8", + "id" : "1ecab23b-5b5b-4252-ae04-f02d82a10fbc", "providerId" : "declarative-user-profile", "subComponents" : { }, "config" : { @@ -1215,55 +1215,55 @@ } } ], "org.keycloak.keys.KeyProvider" : [ { - "id" : "491a8374-2165-4639-a5e0-ed46056fc8ef", - "name" : "hmac-generated-hs512", - "providerId" : "hmac-generated", + "id" : "1c046623-2414-470d-885d-676b218f903a", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", "subComponents" : { }, "config" : { - "kid" : [ "837b86f8-185f-44d7-a971-08fd21361790" ], - "secret" : [ "0h-TQyfcIzi_NhnjYmj01XQE9cT91JiiXTyQiP2vUNCaEVxYzuEiPrWdKyQrCerNrQWl_BfQvF752F0Ri_CeaCb4oOgdbXtpYHIe39Htm2sR6XboBAo2krQiigZpXpiBFq9vnZoCqk7QYbdPQfCB3b1sPqiQksjKPlU98MBVyTs" ], + "privateKey" : [ "MIIEogIBAAKCAQEAtjMAtyi53OP5PDhUMn0XxLfqUt2Z8nYezDWdxVOSGLRb/zYLK3WaXCwrz88OyBeDHq4QnwD3kGtBmVfJl1jPwEP0QBAVeI3adQJnJhqUpKp7a+ERFQiIlgxhtTWauZxZfwJ1LqDRZ65Th+n5Wldd27J08ex47AHjerCTi8VESCI1+zrZpteNHbHhM30KfXMobnM3wjRtxu8TGtMNZvLA+X1y2bdL4tCcjqBp1JoAOJZRPm2XW6HDmGW3z/LZYI3qffr/xo/JWtjFCrjSfIuuy41bvxkGxkt0AJu6wrlckoAos9PhzJrXIZoqxqdJ5KECid4PlBXxNu3ayT5qCCuuHwIDAQABAoIBAAjqcAOGe6niggS/YOdjlbErqszJSUpDG3i0uva4AzMwSDwx4dQLmjUeeDpgEIIcHG945xlQy8yGYxxk3lmIoAnxiVdFMjfHAUSujGuh61oveYCq79IOq9hj3LgoWlzw2LRNY3yXpAel0TKacXhJRC+HCQ/5mWU7Jm2PjHjPe2roJIOaojg5Z9oUKX4do69aZsRYjukr4MOn79MJ8Y2t+CCFkpRunh753c9I7FjTBMr0ejjLPcdSRl2qQcVeS9XExCdxB9u1sSn7WftfwyKVoks65DIVhANfvNjzDa3gDWvEETjNm/HPmpKcb1fLilvxjGZkknnzj0e67cJxfYGhyrECgYEA386QURCw4oXdTUs1ZbF3HEvc+5URl29IDIKBAPkS+euIXqhTXM0DXrvjNM+7ISZyO8giYTvHxOl1/uKgAEtpapdlkMdLTgQW5p46rQXpufQrn9mwyJlKI39kgyTnmqZMNjBDoe+/Uq9DVjhldRmXJ+snD/T+hsIbuMWMwt2ONLkCgYEA0GhIroPSNH4gIHUpPwUh9HJ3Ungb5ckwIJ65nVekFWdiwDdci7woqJ4TXjqkyf/CcXqlsA18yKV3oVQiI2UUYYzs0YW6tphplbmLb8DPEUUge48PJmWKmLEea9P2X6wQbQ5kr1hiJvQ252BJe24MntXgW8cpMst+mK9g36xOvZcCgYA3vvfreUDV64oH6qfOQLnubmcIs0TCd5F2rDr9xwyW+7fn+/1nrBkey6X4TZXK2Ay0H1GQ7pb/0Tb22fQInsAPMM63lSyIrjQWFWuAFWz2SH9lPY/vJ190IBMlJ1gZCTsKdFMkTtdU/RrEqx96X3lrFAOS0e9kGY1WJL6++vik4QKBgEjPJhVSGG4eYjr0s6RAtswf8W/uZlCxKQ88ZLyDkd+obueYb8yhv9Ko5ztUYZ3wrI3Yu2n2TFIM/O5v5j1XYvdxtIq+nayNMtYMLJquUalG7UI9iJ1xfCo8NtSVCM4D3vk6vhJEXoYda9EJ4qIsoFwdfHST7+C/F0tgegequxehAoGAesBnMgX8m5uENZ5CzeX2jmcz/o01Kr6RmVyo0DFILOhhyO8cIyQg96r1f7/D73Q8GZ5V23FB9y8hgU9dtGpoM52Ty9HA3miceaKJjTkd9c4Lq7Vt74Ho0/WY+LE7lCL3hHBQd+79LfZhSnTrZx7rYMnJjB5qVhJ4jheMumOd4rE=" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICmzCCAYMCBgGSDEEpTTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwOTE5MjE0NTQ5WhcNMzQwOTE5MjE0NzI5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2MwC3KLnc4/k8OFQyfRfEt+pS3Znydh7MNZ3FU5IYtFv/NgsrdZpcLCvPzw7IF4MerhCfAPeQa0GZV8mXWM/AQ/RAEBV4jdp1AmcmGpSkqntr4REVCIiWDGG1NZq5nFl/AnUuoNFnrlOH6flaV13bsnTx7HjsAeN6sJOLxURIIjX7Otmm140dseEzfQp9cyhuczfCNG3G7xMa0w1m8sD5fXLZt0vi0JyOoGnUmgA4llE+bZdbocOYZbfP8tlgjep9+v/Gj8la2MUKuNJ8i67LjVu/GQbGS3QAm7rCuVySgCiz0+HMmtchmirGp0nkoQKJ3g+UFfE27drJPmoIK64fAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAaSiN9JaOTMBNblfin32x8ExMZHFWpVeILIj2jjxhEOKV/d9SHkpKVfccup5aqJzn9mP9oHGNGbekLwW/X/3VWSCIQ7AtVrmmgtJgXEQ5zcW4CQRqtFdE+0IhbKD0Ui06qmU1kEpAUIhn2w9rquDPiHqHxR6K4iz2heESGhbKsYHLrX0zcfljV6ZiipC2OLK1ca+1wg1Ba3FUGy9+kAto1b6VOXS/+dLSxcpBpFzfiyDO1ijavD0y/J8gtNN0+kAilC2EcJQfIiLKg10FCDyHmG9IFV0g227rYpCGzQA5ljVLkB7mXkz0ieofbcRFqyuwRPve+JwBhonlYDTumDkMc=" ], "priority" : [ "100" ], - "algorithm" : [ "HS512" ] + "algorithm" : [ "RSA-OAEP" ] } }, { - "id" : "039e4b49-09f6-4eea-abcc-5629093d48c2", - "name" : "aes-generated", - "providerId" : "aes-generated", + "id" : "96b35fdd-5cff-4ec8-aa78-a10b25a8889b", + "name" : "hmac-generated-hs512", + "providerId" : "hmac-generated", "subComponents" : { }, "config" : { - "kid" : [ "b38fa3ab-54fa-45ea-a3ec-53b06c6ebd1b" ], - "secret" : [ "ECSK8BJxfH0KE7WbtROdkQ" ], - "priority" : [ "100" ] + "kid" : [ "366e0455-d4e7-48a6-ad3a-50faee7b1bdb" ], + "secret" : [ "aHkCWF79XyKGruLZzIu5GuPq6Olu5kLhQKf0g7btkTQWrX0jGm3HfuEKiZm_-sMhonsafkU_GAerocJGHT1-GYsuDCHixJk0hcfY5H4u3PA1SJrA4g5qVCYocdVtAS-LsxpBdfmbnKBjegKnXrS74Mbo5B_zEMxzducY0A-eRu4" ], + "priority" : [ "100" ], + "algorithm" : [ "HS512" ] } }, { - "id" : "edeffc5b-ad14-432b-8816-98178a0b0292", + "id" : "686cb55e-b9ac-48a9-bbe7-470d6fa1304a", "name" : "rsa-generated", "providerId" : "rsa-generated", "subComponents" : { }, "config" : { - "privateKey" : [ "MIIEpAIBAAKCAQEAqgJfKoXnolBDcsRHxXxwwe4eQOcnJpDZ2agQ5hbtOXRqbPeKBlcRHUf6ecjqQjdaWmUOJxIGSNbYNSW/Lw3pyRL939xZiUOugJR9iiYru7TjqPj5Ts3qALryBcJ22iDu3goCysxQeQfWF2U/PuVKZ+OBIZXQ0/Nq6WRIMLopIImh+lVuBTkQzKDgDMIZ88469JFKbWpRZ2zxX5zthhDBtGpDi18mDaZE97Je1d8nvQI/0kWzj2C1pGhZnltEhdHG+SC12hEi8MmUYk7tDUQhJpl3jxIDkQDdGXplks+Hnercj41Hlitt/jT6zjw/AqweGmmNGRYCCD+KTAsAJtG0SwIDAQABAoIBAEza86CqljOHa2ZnmzaI8gSJm/2lQcqqcwF1e+Y4eRefLDmEkk4ZcDA3iOEjVduHYH467vH0sQier3EfVlV0SbrPrhtUZtmp0ipodnRMmzqpJL4Ph8z7Q4z+9khqSAaGGtYf2nFJehus0jkTWUsaps9eRtMjAhu/EBbgcc4takg9k25hfg4Aj/VWRfdqYK9yT6zmgMhhi9TnxHACQtpyz5MfMUgbDzvg31ztqbRAU2YPPbnCjmWcFrZALCq0sBtQXPlZbthOcyiGHvUuTBMUuTeXu2Tbo9Rk7oLiLDYKDtC8cOC/3ldJxTEGVyA4vCC+D2m7g2cY2FEewsC2648GiLECgYEA0jbseH337iinUOTYxInvCErS1PD5WrOuuYRP2qCp8rz4UbVRWPN3Y5fvyTzTZ3WsFRo1vTsEvPEDioFj7JuOI+SAxewW82cvpWSdtBzc4Rouh/XQuIy3gygagHdQaD98yWpEwH+fX4nmRoe+g5YMsgVQzMM/Cr2Jo7ICCipNKXMCgYEAzwmx1OEWT+A1JuYrZmuMVy1XYJf+a3pqPod8/PFCdxcvRN8QM0wS8VOenbQgNPFmDOq/JM6JFz4xAQgrSxeZJveSK7nYUYoFtKeRSuZj8mQl2mXTLYRRnxIS8IC0G+WlqgdwtxGjX63m9jvu7on5SyDZSKEmhs5/tP2u4x2M88kCgYEAnpa0+4n9G30sDQk4x71Pya+5MtDBLb5U2LyLCeMfk3Mg23Ow9SxoK4iaa/Upf+n0cs8dL69wuaISC9HlssEAEO/4fljIT8TO2zX3C8SilmgMJqI6XqA6agY9SCG7VYpf+Avl5lvhvk/om9kYz2jKFxuPg4rg6pdnWUmX5FdZcyUCgYBtAtLCnt2Loyb5W1ngrKIRSMtoDb+lQahtUhOKb1GquOdnoPe7usOCk5/Bs5T9q1krVfLc426lcVaGD5IUENHQBazOHyV6EW1dqJlE0bgwaXDQ5KpjnfcIBZE5Vtr+kVVACHjdu4jFGSCx5+6vZLCBUUN3DXrmohX161jJNsb/mQKBgQChMC4QSxsXMYmPAx4L8QeXN0efQDKmdFc7afyYYNHIIaxKhgJ9YJCFj0demYD2ml/TldZDjvNWj5t+vbNcHWU0MokznEb/YpYRmj//yz4KwNe7qCnqHW3FNeaGf+nONH0dByPkE6jA2UuTwY2m4qDVfx7Pv+WwRF3mqeDXdfe6yA==" ], + "privateKey" : [ "MIIEowIBAAKCAQEA1jaSmeEVgvMUvirpsQ0gtrWJuunJ5gQXk5HZAcx2yO4yDWGsDO6qAMTVmdsjO6EkTIkL4BPqAyE/0DZ89VkEf+69OXWhdFXD7dv0ZufBOZezpTDiZ6cdgQCyaofAsHRmWekaEAgJMTZ6iTT1973rK1W96cXukC2ozk+YDG4w6PCZDpfTpq+KYol8qt0qCjfqPewgHZ+0aEHmM9DeX5RO8o/Z+i5N88R39VnsNYpVvTIlRV/GJ6d+zLDI7l50QxKPNngruD4Z+B3kYQe/e5DcJBoKL45oNfkb+uiV/OuabmyajN1RS8u0FrVUd0emS02dkLuL6TfyYsVInRLzAiQMNwIDAQABAoIBAAs35Bk98e/1MKwS4uvcSaR367odCJn3XeVjDnqAeDoRS2VrAjp9J0G6DTZXr8fYKmaoXgsCpU87pwli88wE45jwP6WqNOXloJ4CK7xV58ckht/K/cMQO+8nwlrqOBulmj9G12VpM6i0TITcqq2qRbjJGT83F/AiDASd+NMHKaA78jj+ZWHmFarTIwfB03Zdznb/8vRGFSsyjhQgOPXZZoZdUu1GJEmnY81/yyZP92n/Cf2gjhZU5obzDHDBk2jhS50M0PVpcem8VD5gIKFAhOZWCJfZUj34eUbcEgg5/6QQE3KAJ7GGSu+pQ1B9l0dJ6EfGv4vl+V4jpfO7FqWi0/ECgYEA8/RknVDMkM3lZ33Vwri+6N8pwlYJ2kRBQEYFJK5TtKu2fSXTqAFhodYKaIJh/f5kQjJniFf2p4Rtmwwde/aoxAdVBinTKRNKlSz4kM0c3vTOCkVSJrW6t3zyTAPBkzk5iPMTi0ghQJ46zUjf7UZIsB6NjI6cf072cBlxUYYaiKcCgYEA4Mo+q7po0ahfLH4hNQ5fa/JWw3OyCdTcJDGTAcB9v+yVXa4SmoZxfwxuuyYAsc0dxa+wZZNMx1Tf6QQUFIVlXlvSLid+LEpClZ/clguQzl3OyIq01XAUSAYsBoxMzwaT9VnSKaN/WrLBMKPG8738GJgbE+EzV2vlUJ9/432xQfECgYBp5vQunr7PNbKapLPBHjYyHX6hUHxidjLlVgAxlkPcMJa96UfirQbXHHXUPJWRj3eyjPMI6za2LfTu0+mQwNkukAhG7q0uLaO48pbNNV2NJDS1nLY2+7kcom8EtLS51qO1YeBgHGXjCU15hGNBO7ueSQUluVsSoRK2QzVAMLkgDQKBgQCwUHHPqKrGp9XexB+vydI2jSJYs8qVw4vYJ7oyyZTYkOynSf31jjY/fLTtveUVkNklUaR+R4cVYhEuZ7CIWAkmdcbpxLhGbQjE61rNpcyy0Ql8aq9kKkD+LTki+bDVQUeUTht15XPi5Ap76DoIvJ+betLiSOVIUKzRDAn3mYMLQQKBgDTNljhvgzvlVvtm0+bpjtJk5j9sJ1yVo1iD8hGKZoFPUzqQ0DFcvf3NXQsZLVeLuyN9WajiuTqhuEp3zfIWyajhd1mPpNl/ZO1j/Ct4rY94awT5QXsZurlrj1HmUTFkmGGJLhBZeu4YhmZBSRojJscbzFeMQmS474Wid5lZtw9I" ], "keyUse" : [ "SIG" ], - "certificate" : [ "MIICmzCCAYMCBgGQN2wk5DANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwNjIwMjA1MDUyWhcNMzQwNjIwMjA1MjMyWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqAl8qheeiUENyxEfFfHDB7h5A5ycmkNnZqBDmFu05dGps94oGVxEdR/p5yOpCN1paZQ4nEgZI1tg1Jb8vDenJEv3f3FmJQ66AlH2KJiu7tOOo+PlOzeoAuvIFwnbaIO7eCgLKzFB5B9YXZT8+5Upn44EhldDT82rpZEgwuikgiaH6VW4FORDMoOAMwhnzzjr0kUptalFnbPFfnO2GEMG0akOLXyYNpkT3sl7V3ye9Aj/SRbOPYLWkaFmeW0SF0cb5ILXaESLwyZRiTu0NRCEmmXePEgORAN0ZemWSz4ed6tyPjUeWK23+NPrOPD8CrB4aaY0ZFgIIP4pMCwAm0bRLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAE4JX1hmGcOm/bCB21uOP1+Kkc6uydaZPbvxbibEk1zqtHOnPOnJwNw4m6r6POdZD5k54k0fq4KIIBF1zZwCmwLy+OFto5MzIo13gQQTiieFjMxV/b4XfhaHwYJJiwhDyrZQYjMNL9JvNfKjcBBlKdIhjDQT4M8xLo0ViJnKt03C1JdVBcSiopa3PNMjqNpzay8QosLQ9bfkv3X1mN5NXTkyY2mOHpRhJPzvUrP+ZCUws9PVNgpcoBxQ7SA5E2u67yHFN0x9C+BxbDBvhicoGq6WyT3TSgGHf6PjaAafmiYhmL3/tdX1fM9sh8qZI72296q8pGx0T+Ubs3/WcuLbuyg=" ], + "certificate" : [ "MIICmzCCAYMCBgGSDEEoqjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwOTE5MjE0NTQ5WhcNMzQwOTE5MjE0NzI5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWNpKZ4RWC8xS+KumxDSC2tYm66cnmBBeTkdkBzHbI7jINYawM7qoAxNWZ2yM7oSRMiQvgE+oDIT/QNnz1WQR/7r05daF0VcPt2/Rm58E5l7OlMOJnpx2BALJqh8CwdGZZ6RoQCAkxNnqJNPX3vesrVb3pxe6QLajOT5gMbjDo8JkOl9Omr4piiXyq3SoKN+o97CAdn7RoQeYz0N5flE7yj9n6Lk3zxHf1Wew1ilW9MiVFX8Ynp37MsMjuXnRDEo82eCu4Phn4HeRhB797kNwkGgovjmg1+Rv66JX865pubJqM3VFLy7QWtVR3R6ZLTZ2Qu4vpN/JixUidEvMCJAw3AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAJl6tFjscJN3s1xZ8WMykK6x8rYDFwGB/rsRnh5NiNJSF9c0Uv0JDXjAT5ShTBOr1YBahcIjsGGmoDgayxWCWnVuDGiJ/ChUmZ+pzw78g8H2MuXyG8L/46/73X7CHc3Xd8nXA+gCU1cCTubImQfAa+XTDvI359LXkd8V+Euo5JCnaeMT//73p8VS25exoLuO74H9yCHtR1pdIJf4ChAXnDF/kUPJk0Xzzn9cUOv7kZYSD0/ZXX9zljuF11gmC/qtSpdVlrP0n3xkBFXPuCb6XxuFk1oVyqDBOKLaO86qzebnjYLaaUUO6WgLlg76zecgyL9elHEbDY8B05ss91EE1kY=" ], "priority" : [ "100" ] } }, { - "id" : "1e8aa950-265e-44a7-aeec-bf9e9b8a7250", - "name" : "rsa-enc-generated", - "providerId" : "rsa-enc-generated", + "id" : "7f09e245-5513-4c92-8162-f95bb1f160f8", + "name" : "aes-generated", + "providerId" : "aes-generated", "subComponents" : { }, "config" : { - "privateKey" : [ "MIIEogIBAAKCAQEAysVkfW/UrOSBpWTCpJMdTugBWemjdE1TZeVQnvACtV6o58QY63Idztnobb1XfHqpmn3y8qTcNx2jRL9iWuMMoke49lHpckVcOl3Lv+LzSu0VenwsN7FE4kUKb9QUlXOY+wTIBNtqHgiqvMKKCdMwNesWFDeau8rpM14m5r+74Dw+naYUv+/n3HlI0S5L3unKxEHmLAFA1jgPij6E84Gax9zf0GiwvXq/YAF6vksbmE5V6s7btU2yuHxjAF2YsldEnbYbFXeUS+Y6JwZ9/Yhk8Rfm7Mc8bKeBuSUl6SmLjAv7utp8ePY8ArK6fm5eMhkhZHUKcpZ4vrb1noa2y3V9VwIDAQABAoIBABdh4SSrMKsp7olUBTNVLkawb6Ieqb/6QBO6oywGIUnTkJv+pkuq7SUH8SA2eqWFaj7BJ12JBUaVya4JI8kMmvhbrPM6nuDpKVQnB3J+iUT/8eod8jtkhbz8mSeBcp4z+6rL8lodCIT4xYzezMGKnj9EIgJS0dULS7j7XSEJcHDQTO7hIAt2QEJYy1ftAsf0zZ/6KBsiNO1h4C6WcOgsVLS+YSC6VTUQi0eeqicCp/SLIFaXE58pVoUlsKAlMnH2syzUNLzrYFnblD10F3fmrg09VzVIEG9lA5CkNHMDXf5LC2cwqo4x/OrPr1Fo0fOB/CrNe1TToVHO5Xz8JJ9beIECgYEA91oYyXAXRus5ndulU8UfODkJo0f0NWKlss8dYz8t27uOgne2blB6LsczD8XgH/LQ46GnKa9+vMwqcuOjb3b61kbLROrm/Qfhba8dcuPsCUvJvChM+DUqi9wETnOBK6PadwBUWTb8VAghi0eenThc/GMhgKyQjEnyD18yurV+B7MCgYEA0dxHO7W1LtVM7zm5NHRodr2KuzbOiHwDW/4codd4KlNiCekE+6BL48lt4jJWmmLmydlvQOWSm3ZLa07BHoLGTmxYzriP9e/JbMWstzoxYmDPMNI7kDQ7dcM1/MsHAhYjGSiAHeBaugSeZByFNOe3RxQmWF/Nh3Y1Bl1DTymn4c0CgYAtB8b5bSGftJURqvoHLRzI5IFfq2rHCUV3LwN/nPHhTdzc3aRlotsLhxJBrdlml5L1zekbyqo8/sI/ljebxEJYHh1FV6pjqDqe+EFZOCsxag245nFUwoETYyOZkKeUZUkRXwr8DumS9sP8kjZLEwbCn91qin/qOlAKAl++4+mkxwKBgE9AHVJqK1LVUCljJhKuBykYKQTMDLC0DFy4GL3xbbqmJHbTnYMcpKwPzERIeDXzNW5ygzYBvByjTpXmdr1760GAXwUp44ufkvRVrgS/oBijsHqiWcX6Q54UKxYc4bei/nwotEEUEY7/4YSy1IcHHkpkTJrBCw+lzx5pJ9sEQxbdAoGAEHkn9JTMnY33t2XZvUcjWT2MzKfibRl9A9PLxqiv4HdlB5Zc4YJlV2oXsgWkWsDaLsISAlMNMMYNV8gF/53eC+/dkgG4IVvgPkT/dPEpTvW+Ke1IT3tqWGclElCdZHE9RphJJ8A0kfUTirVNylewt+PdD8ITD3yrRt2GGmzPY0M=" ], - "keyUse" : [ "ENC" ], - "certificate" : [ "MIICmzCCAYMCBgGQN2wlfTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwNjIwMjA1MDUyWhcNMzQwNjIwMjA1MjMyWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKxWR9b9Ss5IGlZMKkkx1O6AFZ6aN0TVNl5VCe8AK1XqjnxBjrch3O2ehtvVd8eqmaffLypNw3HaNEv2Ja4wyiR7j2UelyRVw6Xcu/4vNK7RV6fCw3sUTiRQpv1BSVc5j7BMgE22oeCKq8wooJ0zA16xYUN5q7yukzXibmv7vgPD6dphS/7+fceUjRLkve6crEQeYsAUDWOA+KPoTzgZrH3N/QaLC9er9gAXq+SxuYTlXqztu1TbK4fGMAXZiyV0SdthsVd5RL5jonBn39iGTxF+bsxzxsp4G5JSXpKYuMC/u62nx49jwCsrp+bl4yGSFkdQpylni+tvWehrbLdX1XAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAE6H+HxjF6/XOclsHEMVqkQMoHbOb/j+enSaRgLsroX7ir8Xi1mW9HSLReI2H/B8oM/KrVflcGnkE0wD4QR82OR39F/HIbIirwtF96dnBIYs6SzgAUIPrGoBHzAF1yfwcq3utU64yOUKFyS+Lh9LWEULAfMavJJmzYBDSvnzYB/SefOJ/HLLGjs1DLlI72zK9wRisFzlb58Afmmg1I0jAb24NMNNVHK2gY2qIXN4zYcpEKt02dqBnQwyZz3bwzxZXur/+xvNKb+whP4zxNtp6vPiAu9sS+fK+VFCl9tUmaKeDZ+Z1rU1xSJiJ/5XxBmlOdTo5fnGyfWCoQc6pg4OPXM=" ], - "priority" : [ "100" ], - "algorithm" : [ "RSA-OAEP" ] + "kid" : [ "99b8c5d8-b422-4a80-a89b-2b314e88d878" ], + "secret" : [ "ZZ6PFzoCmFp48E0-F3TVEw" ], + "priority" : [ "100" ] } } ] }, "internationalizationEnabled" : false, "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "28655129-e787-442d-82ec-2175afcdedbe", + "id" : "c91487d4-f795-4de6-9b52-44a98ff08b17", "alias" : "Account verification options", "description" : "Method with which to verity the existing account", "providerId" : "basic-flow", @@ -1285,7 +1285,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "b97ef93b-4707-4427-924c-06b12a9d6b42", + "id" : "a2d3a758-1964-4082-b8de-67d214d20b73", "alias" : "Browser - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1307,7 +1307,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "b404c2a1-97cd-49f8-9ff8-51c33a2a475f", + "id" : "6f0f0386-b936-4824-a945-585b427cd239", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1329,7 +1329,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "d73479e8-8ecc-4a59-a988-2b70dc635f32", + "id" : "d2e29c8c-a3ec-4089-adb5-c6ac6b86cc6d", "alias" : "First broker login - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1351,7 +1351,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "77e2aa4b-7ac5-4540-bcab-b3cdb874d0e8", + "id" : "d0e10cd6-f0c1-44b7-a3bb-82c2af613859", "alias" : "Handle Existing Account", "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId" : "basic-flow", @@ -1373,7 +1373,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "906e3fe2-9aca-4e2a-8452-207437aa58b2", + "id" : "0138758d-c773-4ee1-a96e-7a49c52fac40", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -1395,7 +1395,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "dfffe646-6381-41c1-984b-daa6ee2c361d", + "id" : "707a42fc-9d0f-4c81-84dc-0922d4e0b81f", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -1418,7 +1418,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "eb8571c5-747d-41c9-860f-11918fd78424", + "id" : "779e49d0-6aad-42f8-8f15-b53718635b92", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -1440,7 +1440,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "379aebe8-0bd2-4987-81bc-1445a1c874f2", + "id" : "c762e845-dcf7-4109-a2f0-2946a6adc859", "alias" : "browser", "description" : "browser based authentication", "providerId" : "basic-flow", @@ -1476,7 +1476,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "d1423eee-21e0-4f8e-be0f-3181391271fa", + "id" : "d1c1432f-8205-4690-a0aa-84893776141c", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -1512,7 +1512,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "265a3aec-eb37-48ca-8dae-343b89704cc6", + "id" : "28ab037a-7672-4ea2-bbd7-0a616cb42d01", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -1541,7 +1541,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "fa1af060-848f-4c0b-87ce-aa2479deb144", + "id" : "0a96e97f-e194-4f49-a992-4bc51b07d34f", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -1556,7 +1556,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "479f337c-603f-4b0c-855c-81076a300634", + "id" : "977365e9-b7c8-4cc3-88a1-fe556a68e490", "alias" : "first broker login", "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "providerId" : "basic-flow", @@ -1579,7 +1579,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "ca92fcc1-d758-482a-9aff-24576d1bd58f", + "id" : "310e7c54-e96f-45da-a57d-4b21d490ade9", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -1601,7 +1601,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "b12d71a9-8281-4e29-b964-9c6b0cc9f3f4", + "id" : "058a7bad-aa61-4052-af90-0ed63c829723", "alias" : "registration", "description" : "registration flow", "providerId" : "basic-flow", @@ -1617,7 +1617,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "8dce7cd5-3a30-4a96-b9da-c934040d09f3", + "id" : "52d266a5-2e08-47be-939a-a8871ed2a16d", "alias" : "registration form", "description" : "registration form", "providerId" : "form-flow", @@ -1653,7 +1653,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "f0e9cd6d-b215-42bf-90da-bc6e6f26fe38", + "id" : "65663da1-53aa-4a45-aba1-e0ce8c2e7500", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -1689,7 +1689,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "3ebd8362-d11a-48e4-8ef0-3e03a7defd68", + "id" : "150df60a-42f4-415a-b0b1-89a9e9cf76d2", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -1705,13 +1705,13 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "56353b42-24a4-4e59-aa2a-b027914d8f28", + "id" : "40732755-fbff-4716-9f05-d50581b4b493", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "d860c38c-b89b-41e0-a70e-953dd6252f5e", + "id" : "3e4cf76d-9d20-46ff-811e-2a7508fa7d68", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" diff --git a/src/test/resources/import-files/exported-realm/25.0.5/master-realm.json b/src/test/resources/import-files/exported-realm/25.0.5/master-realm.json new file mode 100644 index 000000000..b903f8459 --- /dev/null +++ b/src/test/resources/import-files/exported-realm/25.0.5/master-realm.json @@ -0,0 +1,1833 @@ +{ + "id" : "55629008-ce2b-4083-8543-aab9be5c8770", + "realm" : "master", + "displayName" : "Keycloak", + "displayNameHtml" : "
Keycloak
", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 60, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxTemporaryLockouts" : 0, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "2d17c8ae-3af1-4c17-892c-394b5dfffb8c", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "55629008-ce2b-4083-8543-aab9be5c8770", + "attributes" : { } + }, { + "id" : "b6f32281-43f1-4c5c-9175-a33c0b098198", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "55629008-ce2b-4083-8543-aab9be5c8770", + "attributes" : { } + }, { + "id" : "6c3542f4-d34e-46c1-82c5-550fb579a747", + "name" : "create-realm", + "description" : "${role_create-realm}", + "composite" : false, + "clientRole" : false, + "containerId" : "55629008-ce2b-4083-8543-aab9be5c8770", + "attributes" : { } + }, { + "id" : "305c2c19-794e-49af-973c-b634e0f80e7f", + "name" : "admin", + "description" : "${role_admin}", + "composite" : true, + "composites" : { + "realm" : [ "create-realm" ], + "client" : { + "master-realm" : [ "query-users", "create-client", "query-clients", "view-identity-providers", "query-groups", "manage-authorization", "manage-identity-providers", "impersonation", "manage-users", "view-realm", "manage-events", "manage-realm", "query-realms", "view-authorization", "manage-clients", "view-events", "view-users", "view-clients" ] + } + }, + "clientRole" : false, + "containerId" : "55629008-ce2b-4083-8543-aab9be5c8770", + "attributes" : { } + }, { + "id" : "3dab2fbc-247f-4615-a0fe-f89c382f1c61", + "name" : "default-roles-master", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "manage-account", "view-profile" ] + } + }, + "clientRole" : false, + "containerId" : "55629008-ce2b-4083-8543-aab9be5c8770", + "attributes" : { } + } ], + "client" : { + "security-admin-console" : [ ], + "admin-cli" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "3d6c30c9-4196-490f-8861-18a520071589", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "fc8c7b1a-a320-47c3-941c-b2f2526bbb1c", + "attributes" : { } + } ], + "master-realm" : [ { + "id" : "a8637f4c-dae7-4edf-b7cd-3b9bcb54b14b", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "87eb352d-2784-47aa-8587-228cb3c3b389", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "4dd68b4c-4f66-411f-95af-1468b0061dc6", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "52d635b5-0654-4ddd-82c7-1462cd0f6348", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "b4209cfd-e1c6-43d8-917e-a822ec23a4de", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "15c8fec9-1610-4ee0-8402-ef7e123e789f", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "6d54aff9-a6a0-4209-bbd1-aac3be464ca0", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "30a6d10c-e297-44f8-8c4c-b0dde377ffd0", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "ac2e28ec-7f86-425a-b96c-f9641cd0198e", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "b4cbdffb-4242-481c-92e4-63fcee6456e1", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "84f688fb-4ff5-4761-9813-0ff3853de194", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "a87c1cf9-aeff-49da-ae0d-d9f4868f1483", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "1c44abc2-96d1-4bb5-b92d-268590ee2cd9", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "901b6ece-ce03-4bfe-8bd6-4402c04128be", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "31774f68-8358-424b-8f7f-33056491eb91", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "a595b1f3-6971-4299-a8f4-c45f37b300f9", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "477a4a7c-d685-4fab-916e-ba4e81d8a5d3", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "master-realm" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + }, { + "id" : "ca550468-dabe-440b-993a-cdbaafcf3ba3", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "master-realm" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "attributes" : { } + } ], + "account" : [ { + "id" : "61a4806b-24fe-4fb6-ade8-ae4297c9eb0e", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "f967a9a9-239e-46c0-ad99-a02461fe8ba3", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "83b4bbe3-3590-4bab-9000-40c30cd74b8a", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "05423878-1b36-4acd-be69-deb4d84a6d88", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "895bf952-95c3-4399-a9cc-c0267dd85615", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "65a7eff2-0043-408a-b0a8-11240b65af3b", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "8dec7ad0-523e-437f-8719-6430a9dfc5ba", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + }, { + "id" : "9338a13f-baeb-44a5-a45c-140508cebcbf", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRole" : { + "id" : "3dab2fbc-247f-4615-a0fe-f89c382f1c61", + "name" : "default-roles-master", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "55629008-ce2b-4083-8543-aab9be5c8770" + }, + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "35b8eef9-8716-4907-be74-94dd7310e79d", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/master/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/master/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "acc8caf3-a610-45cd-b2f1-ce4245274289", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/master/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/master/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "d137a637-7423-4f2c-86ef-0e158a3ce338", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "5f39526a-b61e-496b-b08e-609cc0357a9b", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "fc8c7b1a-a320-47c3-941c-b2f2526bbb1c", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "2e87bbcd-3d6d-4e09-8115-9e5f45b96c87", + "clientId" : "master-realm", + "name" : "master Realm", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "f62d771b-69ba-4fb6-a438-38dd828a820f", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/master/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/master/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "c7fc85a2-9902-4141-9292-198e38482be9", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "2d20ac87-c4c9-4669-8817-72d762740765", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "c971abb0-a8e4-4f02-912a-225cfcd9b459", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "7ee61ec6-ad2a-475b-9a24-85d3c2e7cb3c", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "9ad8bb00-9914-40d3-b5d7-5d8291e9e443", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "consent.screen.text" : "${rolesScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "4de0a385-cbf0-469f-9a5f-392c05c82140", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "6243d0e8-3408-4ddb-abfc-11b695e7b2d0", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "6acd19c0-2966-4b14-b3a3-23d12f93a57a", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "94ca65f7-c8e1-4e9d-9047-a75eba57f74b", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "62962673-ce81-4253-87b4-7f46a3afd696", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "cdf4b8ff-6935-4913-afb7-1837731701f3", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${emailScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "b3338a00-7e5a-4fbd-aee1-bff1f817007d", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "1783cd75-645d-4f2b-a48c-bf2f6d707262", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "46405ff1-0e62-4222-8f33-4627072f3b26", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "consent.screen.text" : "", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "b50eff38-2442-42f7-aef2-3e01effa005a", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "06f6c19f-6045-4647-92da-a9cd0497a4f8", + "name" : "basic", + "description" : "OpenID Connect scope for add all basic claims to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "838ea479-de74-4cd3-8e9c-21f42b3b1b46", + "name" : "auth_time", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "AUTH_TIME", + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "auth_time", + "jsonType.label" : "long" + } + }, { + "id" : "a8fa5167-2d4b-4be3-aefd-1cd42d3abbc3", + "name" : "sub", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-sub-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "3f45efd8-d12b-4a45-b8f7-9f7cec39039f", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "cf4f3daf-4f05-46f5-bed7-6de6fc3a588a", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "83afe61e-c2d6-45ad-b3bb-6f1e76dfb1ce", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "b39d8d21-3b25-4817-a9e7-67f8e059d5a7", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${addressScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "5d68a21b-a4b2-4a36-a97b-d342324a7b2c", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "916bb27b-3294-4881-b301-14dd75538a71", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${profileScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "62e2c9bc-fb68-43dd-9f14-fd1efd689b86", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "b48b6d86-81cb-4608-8809-17b38c6480a8", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "3456d440-c1c4-4cb4-951a-39a0728506d0", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "c9c4d8b0-a041-4ecf-b23e-42f3b2694e26", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "16a90a31-a90f-4c0a-85ce-04bceca33f0a", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "522bd07d-8996-4b9d-8e58-6a8ebbfdeef7", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "5458c27e-5edd-4bfa-90f7-7153cb0f8e03", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "5754217d-7b38-4e40-bad6-c80e94f638c3", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "b801307d-ed2c-4cef-96f2-1e598520b3d5", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "0c9d3061-9e9d-4f67-9e24-03d6d5c30ceb", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "9f451040-74c5-4c2a-97e7-2f9445340b5c", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "9b4231f0-e0ed-49c5-97f9-d1420b5642fb", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "d9870bab-1f80-4f4a-b3f8-967653dc30c1", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "4651b46f-49d0-4e32-84ca-26fc14b6d583", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "2c886135-ef41-45ca-ba5e-096908a7fabd", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${phoneScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "226d6df9-bd98-497b-a50a-5fb47900b3d2", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "d0a583c1-2b9d-4104-b680-97a508d9bfc3", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr", "basic" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "xXSSProtection" : "1; mode=block", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "87057623-2bae-4d00-b2b5-3a51a77575cf", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "05f11c22-2fb9-4fcd-a1e1-0ded5b9de360", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "da12dadc-2535-4ad5-86e1-d1ef956a0364", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "5cc8d47e-038c-4532-a180-7a9a8cd24414", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-property-mapper" ] + } + }, { + "id" : "c5f68155-3167-45c8-9f74-841bf10b1b06", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "cd1ca8c0-a84e-41e0-8274-b361b55ffb73", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "77d72357-68df-434a-8be3-3e38125c7a5b", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "d9fbfcdd-60c8-4945-8cf2-66b63d59ab4b", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper" ] + } + } ], + "org.keycloak.userprofile.UserProfileProvider" : [ { + "id" : "94e6d532-7947-4f4d-a299-bb8ba6abbfbd", + "providerId" : "declarative-user-profile", + "subComponents" : { }, + "config" : { + "kc.user.profile.config" : [ "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}]}" ] + } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "e30b9bb6-81cf-4924-9c4c-6e8ca8422bf4", + "name" : "hmac-generated-hs512", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "20ae767e-f05d-41af-bf73-3de8f7b88150" ], + "secret" : [ "qIK-SLxIZhBtMbvp1WK6SdDwy5iFPO2NPQoShzdwE324Vlb4tzD5l5XTK6-23nDycjeZ3FV_jT0VQzUzD_yl4yKwe6bDMQJKKUW1uUe0zITSrYoEMxrLzVUO0tnKHVc62GuDJI8ejkg_qQuUOV2DhUdxuukaHCRdsXp6h5PSQKc" ], + "priority" : [ "100" ], + "algorithm" : [ "HS512" ] + } + }, { + "id" : "22177e0b-0bf0-494d-a1c1-23acfc99f87b", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "7ed63787-e3ff-4485-bce2-ae75ce554674" ], + "secret" : [ "VH4-cDoW7bSHGmmrLwHB-A" ], + "priority" : [ "100" ] + } + }, { + "id" : "8ac14947-ed9f-4f23-bc61-fee97a322fae", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEAxPUr2W2/HjVHzYG4QTHT2h2YJEfXtQd/YkfXPtlhKgSPOKiKbsyJHek3ZvgoMwNkNj6EdB85DboIWlEkZUd6BD7EU98DjaIGfK1U2oqiRM6VA8W0SN+on+mkhUge8hDRC45yaTibc8ngzDzFj6W0zdGS5+HULGtNBO5kxzr3Iq3mSlHMvTBW/EHxeDThBOrUbwcf6CE7oY01xKjsid8H3ujHTqG63WWmF4nycfnxgzwo1bNspmBLkUVXN5x5p2WZxMkV3bPJ3XRZsNcKnrXbnvLV3RRSHx96nYMSHncyyZv/emhiRey0au3X4uCWh944O6VQQgG1tBMTA1ruNZ+7yQIDAQABAoIBAAY1Geww3sijcj9iWr3HRb+GlkByeTRt55Bf5kNHU54g5aip+y7xyFKGgqX+pTmyXiqtfrwwLbqmhdPe4dBFV+2hUsu36CNDG4Q7bES1ANc9UYn8Zam0Ttq3YOWId902NXhxRV7Wl2OnVavqMGnOFaw08jXXsrmxqgxBPTDgRWC03x/tI/qSsPP/zj4QfcmIFBjjXyg6+07z07kILBI+0pJNuk0wodA2KyD7FuakLgbgQxHM0tB9ob/cuOY11REuQuis8MN0pdP2GEttWxcDhhVlEGuQu+Em5tnxKfM3Z8Q2nJfyCYhBhSvBRNCqVFMp/TSNn9ncw0m3lWbIgVCsFYcCgYEA/LVvUwg30yWbDiqmuPClCpKFfjzQgaHQ/vSvU89xdDj7A6rjKig8MXB2EXk4XN/V66ZcTt4Q041ICY4yGWlfCdxqcaaAjL/iHOKc6/1Wg2LycAsRlC0jejaCHMDdPYNsgbS1DiswZoiB06/wDmhqkRjo60ILRmWTPgyzWcFUvDMCgYEAx4Xa3WQUBtIItZW4z4VC7ALetJ6YHJomGZRvNCkO+HVeadrIS1HzELzdPEmeHNeqqUD0AukJmSuncR4D54WvS+8Ux7zRyTebv87zuBXc4oAmmC+w4sUVOR/r9r5qzPqI4GwTMxmNNzsrzmqx8Vl6q/bR6P+jf+rOBh9heqcPLBMCgYAEywAoiABfDdiKBT8SROYsdCj6AvdFbidDnqpwoX+aX7ZLFIOoegjiOyrSHAV4pXouNQKNMGMLUCOsorjKiJgX3MlcDHdltAH64EVvqGdqqIbGnz8fG1gP6la/at0HXKXDNAU3FpSdbTthI3YfH9XdmKZaR+9kz2pig+Um76bGxwKBgQCPasP7x2gtzuO7wrdpU5zbEOUMZ8NnK9afJHcawzijl5oZ9M1sdqeFLHzKTRB+IvflWW8MeH4Rv7NIOA8OaKWsq1oAiNUzEem+YgAGHpD7rqoPUpiPKKMswKlYX19dn+iriIP0gzVisgG3CjKGDY+D9JLGLJtV423cMMpc46CgSQKBgQC7qB0JWkQVWMvYmXCJugggZ7ywN6pbpWJHmTIHWcfT9KO2xi6YSBV0Jc7RwiCmci71qUfr8leAW9HVEES50eMv2Ney+jPmJXwkTYI9/EJGQpO8AUiEpElGpxB0ZvGf3CCFZ0+W5xB2ZYA78+y/Zbx+TrWNzq3HTTL3nxWUbifpxw==" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIICmzCCAYMCBgGSDEPEojANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwOTE5MjE0ODQwWhcNMzQwOTE5MjE1MDIwWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE9SvZbb8eNUfNgbhBMdPaHZgkR9e1B39iR9c+2WEqBI84qIpuzIkd6Tdm+CgzA2Q2PoR0HzkNughaUSRlR3oEPsRT3wONogZ8rVTaiqJEzpUDxbRI36if6aSFSB7yENELjnJpOJtzyeDMPMWPpbTN0ZLn4dQsa00E7mTHOvcireZKUcy9MFb8QfF4NOEE6tRvBx/oITuhjTXEqOyJ3wfe6MdOobrdZaYXifJx+fGDPCjVs2ymYEuRRVc3nHmnZZnEyRXds8nddFmw1wqetdue8tXdFFIfH3qdgxIedzLJm/96aGJF7LRq7dfi4JaH3jg7pVBCAbW0ExMDWu41n7vJAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABd7Xf3EmGEfGiXKSQeWeuQsvogVcaIp9qHcCxHbkABGgSL+I04wAcigLsV774eMTWlwugjet/u4SE5NN+vh0rXdcKsd3o6co4BkA7GzN0vyCVN8sIKtwnu6wzl66ukqhbLiZwUapa7Dbz+kHJha7rpKkOF5i2p05x9+40eQpgP/vGgfuQuWW3BPMPJeG6Mihj11kATWCIEogAWDwcY69MC6zsMsysAP+gxa9R5HkyvA9xsy7J1odo9MNRPUGvrooehBD9StkG3vljf2hSiflhkXI9SLKpWGsrZf9uVzZMI2NEpe6M541YtFAiZID3GlbQ0R51kD2yMgy0mITeLMpHs=" ], + "priority" : [ "100" ] + } + }, { + "id" : "86cc40cb-4918-419f-832f-20eb0b7b71ac", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpQIBAAKCAQEA4W5uNBxDjiYxBlU/i+tSUl+mDDtGzwYoM1HbEu2SynzdvsUp8jNdvAiSOw53DMz2sfjo0FYo6p2nlCVUwcMm4CseURBsvkdqf5anXkxkPWQ/vUfrb53w68XZ/yElv77MxOzzH6kv1USg7WgO15LULoK32UNk+ppNYqfXlH9v8aCYyFnI8Q35G1tR5PPqKcgI6Zuvr+WK6DjATe0Ce+jqpJ1yV7uDIrR1W6ChIAdaOrU7h+rVyLxRg4Vc32N+X8UT1EQIj2ns5Txy7cCLmW3rT1dHbzat4LKl6WuXNMm/WtkswaSzWMrqsOwKr/cwxRj6JZtyLEF0wei9ss9YS/P0uwIDAQABAoIBABFuxL7q4J6BfZELzpo3XGpaUzDm9JbV1w4A6nwQOyXFejBidtfv+POthgFjIPmwb/NbWEWkJA3gmzDtohxJxxvWucVzC7W7OBUdxVuZdLb6paMxiJddE2BoMG92VMD7NEKWQEbWgohvgjJZtaweAqKGIUl/2LM4c3uJlzY4lKOOrpkA+3KaATI2hmtcZuhzr+8JvaZbt1eX4SYCKCC1/uU0vJ7gtsEQ4fjqlWQ93aJYMnO0J5hDXVcyq+/yp+aOvNZvBTbmgyJw92ybMTvvb25wGY2W6/w/R560lK27MixxUdLm6mQrWik8Sbryk6iPslwSs9kP1Z2DxeiP6U57SoECgYEA9Eca78EwUmJRVuEsmLLTXap3bsvFwsz7TcZwUxodKwDWbYu0Csg+H+crsxnDOjljTY7MDfT6T+BniHTlgt1tWgTyvDroGs+VPNsEr9k5XRaf0hqaD3y0IeEw9wJioaB7Mes/5fjejnwZ4lyD2M0GsSRVxSGXqnzh4fP4xCQ9K7ECgYEA7D/NRbXAxJ2S8J1l0IMmWrE3aecV/00vq51YAXjss/YH/Lv/6WmibgOvAROjmdT6Zpptncd8N6heh7S3X3axQ/RM3uxDFOportIlpAdLN6YM7UOdjKbpGt1iQlPzJJ2ziRIp8JP284N/XlAACtQjg5yYuS067iqwnHx5IuKU/isCgYEAuYUrKv1Q4rCyz8XR5eKiblehvy7ZcfnVvhrAggyqLFfFgosAYNP1gqtB4BLn11dwWJ3j0ZHFbVajqtoE2N+sRhrN8zDVyE7xK7e3Fopma5FcLehwKuTttXFei6pvGAtWpPHipJjfBd2wlt7mb4g+1dgfn8jEdAHGV6G/w881+fECgYEA5LJ2si7Z5vtrDUYxE4KCFHVNYVV0c+pyZT0xvmsjKKrY3I3ZlEjQFpO2S+KJExebNsvzpTNBSlfQ+qm0gdNSkqfh6kLoRU0N/X4tNfZhmANErEIyN8A0E++PeQnva9jFvcE5nEyAWQdIuzHSeKkXoAZtyYTBcWEeCr5sPZr+BHUCgYEAiZ2S2J9a71RR5SjbrpzzWFCwg4WksJzBe8oS7xLuA/zPwv2ITBBVZcYhjpHkrO/ZwE+9cP1dorbLus6r/a2vxs4tIbtaLIFoKDHNsIue9XQJObtVE9CbNSqxksp/F4f8Cm4srrdxdGzYz45jxHvOonNC41HYh4wubqycCwXH+Gs=" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICmzCCAYMCBgGSDEPFSDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjQwOTE5MjE0ODQxWhcNMzQwOTE5MjE1MDIxWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhbm40HEOOJjEGVT+L61JSX6YMO0bPBigzUdsS7ZLKfN2+xSnyM128CJI7DncMzPax+OjQVijqnaeUJVTBwybgKx5REGy+R2p/lqdeTGQ9ZD+9R+tvnfDrxdn/ISW/vszE7PMfqS/VRKDtaA7XktQugrfZQ2T6mk1ip9eUf2/xoJjIWcjxDfkbW1Hk8+opyAjpm6+v5YroOMBN7QJ76OqknXJXu4MitHVboKEgB1o6tTuH6tXIvFGDhVzfY35fxRPURAiPaezlPHLtwIuZbetPV0dvNq3gsqXpa5c0yb9a2SzBpLNYyuqw7Aqv9zDFGPolm3IsQXTB6L2yz1hL8/S7AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAALM8s3LBqBOqVTeDNJNkUJ2OhJk1iTr37F1qNJy+gFIokNzE7FaD7obMBD3hoHnW4pOJEIjfLw2N79lH66lY99M2zxC4jhe/d9yqKxoAhzk5MZyPOUnBR1NqQ/n7qfIE/vfPeNdLhyKV0+6V6fBcimXM0El+PCKag8T4HkiLpLs6MuRVOLlaPwKsXCwr24TWnyhcuTvNFmnIVYtryGyCHvJDApAcvak8HlhKiIiDI1PiEaLgoWbhFHpQQLsSfZ+AH7MTSmlY02BbUSnTtqQLLgKRbL2FWKOztHBRK6+dT1xxmIXiNMncUtvcTx8S4088URHf7CGwsg2goOgFomSGwM=" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "12923561-6b4d-458a-af19-597a0df4222b", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "0741abdd-9046-45e4-9237-2735956a8f67", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "3569f4b2-ebf3-430a-92bd-e3afd3581b39", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "b063c6d2-033b-409a-a795-78b75451fb5d", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "ebf694df-ccde-40eb-a048-704583262742", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "2e74c11b-f429-45cc-a5a2-051d23349da1", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "43ca4f2c-b12c-4ab7-b32e-e7ec918f1086", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "bd7aec0f-5e1b-44fb-8214-49e01adb2a92", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "69e1401f-6146-4217-9c78-60de39b77e5b", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "de753ad3-bf0a-4cb5-8e63-7f1c61cc4ae6", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "c266eeec-c725-4c2c-9274-255066b87888", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "768f995d-942a-491d-9ddd-e30c94ba7f3f", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "2ad6e90c-e6dc-4bdd-b8e6-2bfaa79f5f7e", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "cde7fa9d-d2fe-4a24-a063-21657ff68666", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "3382651b-cd94-4f59-ac6b-c86c5f37916e", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "0b1ddf44-0571-4077-be09-c5034a11bcb0", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-terms-and-conditions", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 70, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "0cb25b58-a1c5-4435-8e4c-3dc5b76bf7e5", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "5f308482-fe5e-4d4e-82ae-e65bbd2775f6", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "14781383-38bd-4cca-9717-f9a2c0ce74a6", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "33b3a707-b5e4-4e06-9b20-837e4620da29", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "VERIFY_PROFILE", + "name" : "Verify Profile", + "providerId" : "VERIFY_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 90, + "config" : { } + }, { + "alias" : "delete_credential", + "name" : "Delete Credential", + "providerId" : "delete_credential", + "enabled" : true, + "defaultAction" : false, + "priority" : 100, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "firstBrokerLoginFlow" : "first broker login", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaExpiresIn" : "120", + "cibaAuthRequestedUserHint" : "login_hint", + "parRequestUriLifespan" : "60", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false" + }, + "keycloakVersion" : "25.0.5", + "userManagedAccessAllowed" : false, + "organizationsEnabled" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} \ No newline at end of file diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 269d26fe9..4fd4c9198 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -1,10 +1,10 @@ + - @@ -14,13 +14,16 @@ - + + {"app":"keycloak-config-cli"} + - - - + + + +