You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2021/03/25 09:31:40 UTC

[syncope] branch master updated: [SYNCOPE-1545] Adding WA > Auth Modules (#249)

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new cb62fbc  [SYNCOPE-1545]  Adding WA > Auth Modules (#249)
cb62fbc is described below

commit cb62fbcc1f1d93d2fa089e9b5dca1619a5884623
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Thu Mar 25 10:30:45 2021 +0100

    [SYNCOPE-1545]  Adding WA > Auth Modules (#249)
---
 archetype/pom.xml                                  |  10 +-
 .../client/console/SyncopeAMConsoleContext.java    |  49 ++++
 .../client/console/commons/AMConstants.java        |   4 +
 .../console/commons/AMPolicyTabProvider.java}      |  33 ++-
 .../console/commons/AMRealmPolicyProvider.java     | 108 ++++++++
 .../init/AMClassPathScanImplementationLookup.java  |  43 ++++
 .../apache/syncope/client/console/pages/SRA.java   |  52 +++-
 .../apache/syncope/client/console/pages/WA.java    | 174 +++++++++++++
 .../console/panels/AuthModuleDirectoryPanel.java   | 184 ++++++++++++++
 .../console/panels/SRARouteDirectoryPanel.java     |  24 --
 .../console/panels/WAConfigDirectoryPanel.java}    | 116 ++++-----
 .../client/console/panels/WAConfigModalPanel.java  |  93 +++++++
 .../policies/AccessPolicyDirectoryPanel.java       |  42 ++++
 .../policies/AttrReleasePolicyDirectoryPanel.java  |  42 ++++
 .../console/policies/AuthPolicyDirectoryPanel.java |  42 ++++
 .../client/console/rest/AuthModuleRestClient.java  |  48 ++++
 .../client/console/rest/WAConfigRestClient.java}   |  28 ++-
 .../console/wizards/AuthModuleWizardBuilder.java   | 152 ++++++++++++
 .../wizards/mapping/AuthModuleMappingPanel.java    |  72 ++++++
 .../apache/syncope/client/console/pages/SRA.html   |   4 +-
 .../syncope/client/console/pages/SRA.properties    |   1 +
 .../pages/{SRA.properties => SRA_fr_CA.properties} |   1 +
 .../syncope/client/console/pages/SRA_it.properties |   1 +
 .../syncope/client/console/pages/SRA_ja.properties |   1 +
 .../client/console/pages/SRA_pt_BR.properties      |   1 +
 .../syncope/client/console/pages/SRA_ru.properties |   1 +
 .../client/console/pages/{SRA.html => WA.html}     |   6 +-
 .../syncope/client/console/pages/WA.properties}    |  11 +-
 .../client/console/pages/WA_fr_CA.properties}      |  11 +-
 .../syncope/client/console/pages/WA_it.properties} |  11 +-
 .../syncope/client/console/pages/WA_ja.properties} |  11 +-
 .../client/console/pages/WA_pt_BR.properties}      |  11 +-
 .../syncope/client/console/pages/WA_ru.properties} |  11 +-
 .../panels/AuthModuleDirectoryPanel.properties}    |   9 +-
 .../AuthModuleDirectoryPanel_fr_CA.properties}     |   9 +-
 .../panels/AuthModuleDirectoryPanel_it.properties} |   9 +-
 .../panels/AuthModuleDirectoryPanel_ja.properties} |   9 +-
 .../AuthModuleDirectoryPanel_pt_BR.properties}     |   9 +-
 .../panels/AuthModuleDirectoryPanel_ru.properties  |  25 ++
 .../panels/WAConfigDirectoryPanel.properties}      |  10 +-
 .../WAConfigDirectoryPanel_fr_CA.properties}       |   7 +-
 .../panels/WAConfigDirectoryPanel_it.properties}   |  10 +-
 .../WAConfigDirectoryPanel_ja.properties}          |  20 +-
 .../WAConfigDirectoryPanel_pt_BR.properties}       |  10 +-
 .../panels/WAConfigDirectoryPanel_ru.properties    |  28 +++
 .../client/console/panels/WAConfigModalPanel.html} |   2 +-
 .../AuthModuleWizardBuilder$Configuration.html}    |   6 +-
 ...thModuleWizardBuilder$Configuration.properties} |  22 +-
 ...leWizardBuilder$Configuration_fr_CA.properties} |  22 +-
 ...oduleWizardBuilder$Configuration_it.properties} |  22 +-
 ...oduleWizardBuilder$Configuration_ja.properties} |  22 +-
 ...leWizardBuilder$Configuration_pt_BR.properties} |  22 +-
 ...ModuleWizardBuilder$Configuration_ru.properties |  25 ++
 .../wizards/AuthModuleWizardBuilder$Mapping.html}  |   6 +-
 .../wizards/AuthModuleWizardBuilder$Profile.html}  |   8 +-
 .../AuthModuleWizardBuilder$Profile.properties     |   4 +-
 ...uthModuleWizardBuilder$Profile_fr_CA.properties |   4 +-
 .../AuthModuleWizardBuilder$Profile_it.properties  |   4 +-
 .../AuthModuleWizardBuilder$Profile_ja.properties  |   4 +-
 ...uthModuleWizardBuilder$Profile_pt_BR.properties |   4 +-
 .../AuthModuleWizardBuilder$Profile_ru.properties} |   8 +-
 .../client/console/SyncopeIdMConsoleContext.java   |   2 +-
 .../console/commons/IdMPolicyTabProvider.java      |  10 +-
 .../panels/search/ConnObjectSearchPanel.java       |   5 +-
 .../console/policies/PullPolicyDirectoryPanel.java |   2 +-
 .../console/policies/PushPolicyDirectoryPanel.java |   2 +-
 .../wizards/resources/ResourceMappingPanel.java    |   1 -
 client/idrepo/common-ui/pom.xml                    |   4 +
 .../ui/commons/markup/html/form/AjaxGrid.java      | 271 +++++++++++++++++++++
 .../markup/html/form/AjaxGridBottomToolbar.java    | 146 +++++++++++
 .../markup/html/form/AjaxGridFieldPanel.java       |  91 +++++++
 .../ui/commons/markup/html/form/FieldPanel.java    |   3 +-
 .../markup/html/form/AjaxCheckBoxPanel.html        |  27 +-
 .../html/form/AjaxGrid$AjaxGridActionsPanel.html   |  24 ++
 .../ui/commons/markup/html/form/AjaxGrid.html      |  23 ++
 .../markup/html/form/AjaxGridBottomToolbar.html    |  32 +++
 .../markup/html/form/AjaxGridFieldPanel.html       |  24 ++
 .../markup/html/form/AjaxPasswordFieldPanel.html   |  19 +-
 client/idrepo/console/pom.xml                      |   1 +
 .../client/console/SyncopeConsoleApplication.java  |  11 +-
 .../client/console/SyncopeWebApplication.java      |  12 +-
 .../console/commons/IdRepoPolicyTabProvider.java   |   5 +
 .../console/commons/IdRepoRealmPolicyProvider.java |  85 +++++++
 .../client/console/commons/PolicyTabProvider.java  |   4 +-
 .../console/commons/RealmPolicyProvider.java       |  11 +-
 .../init/ClassPathScanImplementationLookup.java    | 210 +++++++---------
 .../syncope/client/console/pages/BasePage.java     |   2 +-
 .../syncope/client/console/pages/Dashboard.java    |   2 +-
 .../apache/syncope/client/console/pages/Login.java |   3 +-
 .../syncope/client/console/pages/Policies.java     |  15 +-
 .../syncope/client/console/panels/BeanPanel.java   |  27 +-
 .../syncope/client/console/panels/ConfParam.java   |   9 +
 .../client/console/panels/DynRealmModalPanel.java  |   4 +-
 .../console/panels/ParametersDirectoryPanel.java   |   8 +-
 .../console/panels/ParametersWizardAttrStep.java   |  20 +-
 .../console/panels/ParametersWizardPanel.java      |   2 +-
 .../client/console/panels/RealmDetails.java        |  59 +----
 .../client/console/panels/RoleDirectoryPanel.java  |   3 +-
 .../console/policies/PolicyDirectoryPanel.java     |   6 +-
 .../console/reports/ReportletWizardBuilder.java    |   2 +-
 .../client/console/rest/PolicyRestClient.java      |   6 +-
 .../client/console/tasks/PushTaskFilters.java      |   4 +-
 .../client/console/tasks/TemplatesTogglePanel.java |   2 +-
 .../client/console/wizards/any/DerAttrs.java       |   8 +-
 .../console/wizards/any/DynamicMemberships.java    |   6 +-
 .../client/console/wizards/any/UserDetails.java    |   6 +-
 .../client/console/wizards/any/VirAttrs.java       |  36 ++-
 .../wizards/mapping/AbstractMappingPanel.java      |  90 +++++--
 .../console/wizards/role/RoleWizardBuilder.java    |   4 +-
 .../client/console/pages/Policies.properties       |   3 +
 .../client/console/pages/Policies_it.properties    |   3 +
 .../client/console/pages/Policies_ja.properties    |   3 +
 .../client/console/pages/Policies_pt_BR.properties |   3 +
 .../client/console/pages/Policies_ru.properties    |   3 +
 .../ParametersDirectoryPanel_fr_CA.properties      |   7 +-
 .../client/console/panels/RealmDetails.html        |   5 +-
 .../client/console/panels/RealmDetails.properties  |   3 +
 .../console/panels/RealmDetails_fr_CA.properties   |   7 +-
 .../console/panels/RealmDetails_it.properties      |   7 +-
 .../console/panels/RealmDetails_ja.properties      |   3 +
 .../console/panels/RealmDetails_pt_BR.properties   |   3 +
 .../console/panels/RealmDetails_ru.properties      |   3 +
 .../wizards/mapping/AbstractMappingPanel.html      |   8 +-
 .../enduser/wizards/any/AnyWizardBuilder.java      |   3 +-
 .../client/enduser/wizards/any/DerAttrs.java       |   6 +-
 .../client/enduser/wizards/any/PlainAttrs.java     |  10 +-
 .../client/enduser/wizards/any/UserDetails.java    |   5 +-
 .../client/enduser/wizards/any/VirAttrs.java       |  43 ++--
 .../common/lib/auth/DuoMfaAuthModuleConf.java      |   2 +-
 .../common/lib/auth/GoogleMfaAuthModuleConf.java   |   2 +-
 .../common/lib/auth/JDBCAuthModuleConf.java        |   2 +-
 .../common/lib/auth/JaasAuthModuleConf.java        |   2 +-
 .../common/lib/auth/LDAPAuthModuleConf.java        |   2 +-
 .../common/lib/auth/OIDCAuthModuleConf.java        |   2 +-
 .../common/lib/auth/RadiusAuthModuleConf.java      |   2 +-
 .../common/lib/auth/SAML2IdPAuthModuleConf.java    |   2 +-
 .../common/lib/auth/StaticAuthModuleConf.java      |   2 +-
 .../common/lib/auth/SyncopeAuthModuleConf.java     |   2 +-
 .../syncope/common/lib/auth/U2FAuthModuleConf.java |   2 +-
 .../apache/syncope/common/lib/policy/PolicyTO.java |   2 +-
 .../common/lib/policy/ProvisioningPolicyTO.java    |  14 +-
 .../syncope/common/lib/to/AccessTokenTO.java       |   4 +-
 .../persistence/jpa/dao/JPAAccessTokenDAO.java     |   6 +-
 .../java/data/PolicyDataBinderImpl.java            |  14 +-
 .../spring/security/JWTAuthenticationProvider.java |   4 +-
 .../sra/src/main/resources/application.properties  |   7 +-
 docker/wa/pom.xml                                  |   7 +
 .../wa/src/main/resources/application.properties   |  18 +-
 docker/wa/src/main/resources/wa.properties         |  69 ------
 .../wizards/mapping/OIDCProviderMappingPanel.java  |  11 +-
 .../wizards/mapping/SAML2IdPMappingPanel.java      |  11 +-
 fit/core-reference/pom.xml                         |  18 +-
 .../syncope/fit/console/AbstractConsoleITCase.java |   9 +
 .../apache/syncope/fit/console/PoliciesITCase.java |  58 ++---
 .../apache/syncope/fit/console/RealmsITCase.java   |   4 +-
 fit/wa-reference/src/main/resources/wa.properties  |  23 +-
 .../apache/syncope/fit/ui/SAML2SP4UIITCase.java    |   3 +-
 pom.xml                                            |   6 +
 .../src/main/resources/application.properties      |  10 +-
 wa/starter/src/main/resources/wa.properties        |  13 +-
 .../resources/debug/application-debug.properties   |   2 +
 wa/starter/src/test/resources/debug/wa.properties  |  70 ------
 162 files changed, 2680 insertions(+), 940 deletions(-)

diff --git a/archetype/pom.xml b/archetype/pom.xml
index 4dda3cf..1315eef 100644
--- a/archetype/pom.xml
+++ b/archetype/pom.xml
@@ -325,6 +325,8 @@ under the License.
         <includes>
           <include>application.properties</include>
           <include>cas-theme-default.properties</include>
+          <include>wa.properties</include>
+          <include>log4j2.xml</include>
         </includes>
         <targetPath>${project.build.outputDirectory}/archetype-resources/wa/src/main/resources</targetPath>
       </resource>
@@ -333,14 +335,6 @@ under the License.
         <targetPath>${project.build.outputDirectory}/archetype-resources/wa/src/main/resources</targetPath>
         <includes>
           <include>application-embedded.properties</include>
-          <include>log4j2.xml</include>
-        </includes>
-      </resource>
-      <resource>
-        <directory>../fit/wa-reference/src/main/resources</directory>
-        <targetPath>${project.build.outputDirectory}/archetype-resources/wa/src/test/resources</targetPath>
-        <includes>
-          <include>wa.properties</include>
           <include>keymaster.properties</include>
         </includes>
       </resource>
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/SyncopeAMConsoleContext.java b/client/am/console/src/main/java/org/apache/syncope/client/console/SyncopeAMConsoleContext.java
new file mode 100644
index 0000000..b3882fe
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/SyncopeAMConsoleContext.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console;
+
+import org.apache.syncope.client.console.commons.AMPolicyTabProvider;
+import org.apache.syncope.client.console.commons.AMRealmPolicyProvider;
+import org.apache.syncope.client.console.commons.PolicyTabProvider;
+import org.apache.syncope.client.console.commons.RealmPolicyProvider;
+import org.apache.syncope.client.console.init.AMClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SyncopeAMConsoleContext {
+
+    @Bean
+    public ClassPathScanImplementationLookup classPathScanImplementationLookup() {
+        AMClassPathScanImplementationLookup lookup = new AMClassPathScanImplementationLookup();
+        lookup.load();
+        return lookup;
+    }
+
+    @Bean
+    public RealmPolicyProvider realmPolicyProvider() {
+        return new AMRealmPolicyProvider();
+    }
+
+    @Bean
+    public PolicyTabProvider amPolicyTabProvider() {
+        return new AMPolicyTabProvider();
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java
index 6a2b169..57f3e2e 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMConstants.java
@@ -22,6 +22,10 @@ public final class AMConstants {
 
     public static final String PREF_GATEWAYROUTE_PAGINATOR_ROWS = "gatewayroute.paginator.rows";
 
+    public static final String PREF_WACONFIG_PAGINATOR_ROWS = "waconfig.paginator.rows";
+
+    public static final String PREF_AUTHMODULE_PAGINATOR_ROWS = "authmodule.paginator.rows";
+
     private AMConstants() {
         // private constructor for static utility class
     }
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMPolicyTabProvider.java
similarity index 62%
copy from client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
copy to client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMPolicyTabProvider.java
index d3b1630..4885481 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMPolicyTabProvider.java
@@ -18,40 +18,57 @@
  */
 package org.apache.syncope.client.console.commons;
 
+import java.util.ArrayList;
 import java.util.List;
-import org.apache.syncope.client.console.policies.PullPolicyDirectoryPanel;
-import org.apache.syncope.client.console.policies.PushPolicyDirectoryPanel;
+import org.apache.syncope.client.console.policies.AccessPolicyDirectoryPanel;
+import org.apache.syncope.client.console.policies.AttrReleasePolicyDirectoryPanel;
+import org.apache.syncope.client.console.policies.AuthPolicyDirectoryPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.ResourceModel;
 
-public class IdMPolicyTabProvider extends IdRepoPolicyTabProvider {
+public class AMPolicyTabProvider implements PolicyTabProvider {
 
     private static final long serialVersionUID = 2822554006571803418L;
 
     @Override
+    public int getOrder() {
+        return 200;
+    }
+
+    @Override
     public List<ITab> buildTabList(final PageReference pageRef) {
-        List<ITab> tabs = super.buildTabList(pageRef);
+        List<ITab> tabs = new ArrayList<>();
+
+        tabs.add(new AbstractTab(new ResourceModel("policy.access")) {
+
+            private static final long serialVersionUID = -6815067322125799251L;
+
+            @Override
+            public Panel getPanel(final String panelId) {
+                return new AccessPolicyDirectoryPanel(panelId, pageRef);
+            }
+        });
 
-        tabs.add(new AbstractTab(new ResourceModel("policy.pull")) {
+        tabs.add(new AbstractTab(new ResourceModel("policy.attrRelease")) {
 
             private static final long serialVersionUID = -6815067322125799251L;
 
             @Override
             public Panel getPanel(final String panelId) {
-                return new PullPolicyDirectoryPanel(panelId, pageRef);
+                return new AttrReleasePolicyDirectoryPanel(panelId, pageRef);
             }
         });
 
-        tabs.add(new AbstractTab(new ResourceModel("policy.push")) {
+        tabs.add(new AbstractTab(new ResourceModel("policy.auth")) {
 
             private static final long serialVersionUID = -6815067322125799251L;
 
             @Override
             public Panel getPanel(final String panelId) {
-                return new PushPolicyDirectoryPanel(panelId, pageRef);
+                return new AuthPolicyDirectoryPanel(panelId, pageRef);
             }
         });
 
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMRealmPolicyProvider.java b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMRealmPolicyProvider.java
new file mode 100644
index 0000000..5590dfc
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/commons/AMRealmPolicyProvider.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.rest.PolicyRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.policy.PolicyTO;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.repeater.RepeatingView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class AMRealmPolicyProvider extends IdRepoRealmPolicyProvider {
+
+    private static final long serialVersionUID = 1671878489700L;
+
+    private final IModel<Map<String, String>> accessPolicies = new LoadableDetachableModel<Map<String, String>>() {
+
+        private static final long serialVersionUID = -2012833443695917883L;
+
+        @Override
+        protected Map<String, String> load() {
+            return PolicyRestClient.getPolicies(PolicyType.ACCESS).stream().
+                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
+        }
+    };
+
+    private final IModel<Map<String, String>> attrReleasePolicies = new LoadableDetachableModel<Map<String, String>>() {
+
+        private static final long serialVersionUID = -2012833443695917883L;
+
+        @Override
+        protected Map<String, String> load() {
+            return PolicyRestClient.getPolicies(PolicyType.ATTR_RELEASE).stream().
+                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
+        }
+    };
+
+    private final IModel<Map<String, String>> authPolicies = new LoadableDetachableModel<Map<String, String>>() {
+
+        private static final long serialVersionUID = -2012833443695917883L;
+
+        @Override
+        protected Map<String, String> load() {
+            return PolicyRestClient.getPolicies(PolicyType.AUTH).stream().
+                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
+        }
+    };
+
+    @Override
+    public void add(final RealmTO realmTO, final RepeatingView view) {
+        super.add(realmTO, view);
+
+        AjaxDropDownChoicePanel<String> accessPolicy = new AjaxDropDownChoicePanel<>(
+                view.newChildId(),
+                new ResourceModel("accessPolicy", "accessPolicy").getObject(),
+                new PropertyModel<>(realmTO, "accessPolicy"),
+                false);
+        accessPolicy.setChoiceRenderer(new PolicyRenderer(accessPolicies));
+        accessPolicy.setChoices(new ArrayList<>(accessPolicies.getObject().keySet()));
+        ((DropDownChoice<?>) accessPolicy.getField()).setNullValid(true);
+        view.add(accessPolicy);
+
+        AjaxDropDownChoicePanel<String> attrReleasePolicy = new AjaxDropDownChoicePanel<>(
+                view.newChildId(),
+                new ResourceModel("attrReleasePolicy", "attrReleasePolicy").getObject(),
+                new PropertyModel<>(realmTO, "attrReleasePolicy"),
+                false);
+        attrReleasePolicy.setChoiceRenderer(new PolicyRenderer(attrReleasePolicies));
+        attrReleasePolicy.setChoices(new ArrayList<>(attrReleasePolicies.getObject().keySet()));
+        ((DropDownChoice<?>) attrReleasePolicy.getField()).setNullValid(true);
+        view.add(attrReleasePolicy);
+
+        AjaxDropDownChoicePanel<String> authPolicy = new AjaxDropDownChoicePanel<>(
+                view.newChildId(),
+                new ResourceModel("authPolicy", "authPolicy").getObject(),
+                new PropertyModel<>(realmTO, "authPolicy"),
+                false);
+        authPolicy.setChoiceRenderer(new PolicyRenderer(authPolicies));
+        authPolicy.setChoices(new ArrayList<>(authPolicies.getObject().keySet()));
+        ((DropDownChoice<?>) authPolicy.getField()).setNullValid(true);
+        view.add(authPolicy);
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationLookup.java b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationLookup.java
new file mode 100644
index 0000000..c10a799
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationLookup.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.init;
+
+import org.apache.syncope.common.lib.auth.AuthModuleConf;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+
+public class AMClassPathScanImplementationLookup extends ClassPathScanImplementationLookup {
+
+    @Override
+    protected ClassPathScanningCandidateComponentProvider scanner() {
+        ClassPathScanningCandidateComponentProvider scanner = super.scanner();
+
+        scanner.addIncludeFilter(new AssignableTypeFilter(AuthModuleConf.class));
+
+        return scanner;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void additional(final Class<?> clazz) {
+        if (AuthModuleConf.class.isAssignableFrom(clazz)) {
+            addClass(AuthModuleConf.class.getName(), clazz);
+        }
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/SRA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/SRA.java
index bf21b02..a82339e 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/SRA.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/SRA.java
@@ -22,9 +22,18 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbed
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.annotations.AMPage;
 import org.apache.syncope.client.console.panels.SRARouteDirectoryPanel;
+import org.apache.syncope.client.console.rest.SRARouteRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.keymaster.client.api.ServiceOps;
+import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AMEntitlement;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -32,16 +41,40 @@ import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
 
-@AMPage(label = "SRA", icon = "fas fa-share-alt", listEntitlement = "", priority = 0)
+@AMPage(label = "SRA", icon = "fas fa-share-alt", listEntitlement = "", priority = 100)
 public class SRA extends BasePage {
 
     private static final long serialVersionUID = 9200112197134882164L;
 
+    @SpringBean
+    private ServiceOps serviceOps;
+
     public SRA(final PageParameters parameters) {
         super(parameters);
 
         body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+        body.setOutputMarkupId(true);
+
+        AjaxLink<?> push = new AjaxLink<>("push") {
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                try {
+                    SRARouteRestClient.push();
+                    SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+                    target.add(body);
+                } catch (Exception e) {
+                    LOG.error("While pushing to SRA", e);
+                    SyncopeConsoleSession.get().onException(e);
+                }
+                ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
+            }
+        };
+        push.setEnabled(!serviceOps.list(NetworkService.Type.SRA).isEmpty()
+                && SyncopeConsoleSession.get().owns(AMEntitlement.SRA_ROUTE_PUSH, SyncopeConstants.ROOT_REALM));
+        body.add(push);
 
         WebMarkupContainer content = new WebMarkupContainer("content");
         content.setOutputMarkupId(true);
@@ -64,15 +97,18 @@ public class SRA extends BasePage {
             }
         });
 
-        tabs.add(new AbstractTab(new ResourceModel("metrics")) {
+        List<NetworkService> instances = serviceOps.list(NetworkService.Type.SRA);
+        if (!instances.isEmpty()) {
+            tabs.add(new AbstractTab(new ResourceModel("metrics")) {
 
-            private static final long serialVersionUID = 5211692813425391144L;
+                private static final long serialVersionUID = 5211692813425391144L;
 
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new AjaxTextFieldPanel(panelId, panelId, Model.of(""));
-            }
-        });
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new AjaxTextFieldPanel(panelId, panelId, Model.of(instances.get(0).getAddress()));
+                }
+            });
+        }
 
         return tabs;
     }
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
new file mode 100644
index 0000000..b43b716
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.pages;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.annotations.AMPage;
+import org.apache.syncope.client.console.panels.AuthModuleDirectoryPanel;
+import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel;
+import org.apache.syncope.client.console.rest.WAConfigRestClient;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.keymaster.client.api.ServiceOps;
+import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AMEntitlement;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+@AMPage(label = "WA", icon = "fas fa-id-card", listEntitlement = "", priority = 200)
+public class WA extends BasePage {
+
+    private static final long serialVersionUID = 9200112197134882164L;
+
+    @SpringBean
+    private ServiceOps serviceOps;
+
+    public WA(final PageParameters parameters) {
+        super(parameters);
+
+        body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+        body.setOutputMarkupId(true);
+
+        AjaxLink<?> push = new AjaxLink<>("push") {
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                try {
+                    WAConfigRestClient.push();
+                    SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+                    target.add(body);
+                } catch (Exception e) {
+                    LOG.error("While pushing to WA", e);
+                    SyncopeConsoleSession.get().onException(e);
+                }
+                ((BasePage) getPageReference().getPage()).getNotificationPanel().refresh(target);
+            }
+        };
+        push.setEnabled(!serviceOps.list(NetworkService.Type.WA).isEmpty()
+                && SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_PUSH, SyncopeConstants.ROOT_REALM));
+        body.add(push);
+
+        WebMarkupContainer content = new WebMarkupContainer("content");
+        content.setOutputMarkupId(true);
+        AjaxBootstrapTabbedPanel<ITab> tabbedPanel = new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList());
+        content.add(tabbedPanel);
+
+        body.add(content);
+    }
+
+    private List<ITab> buildTabList() {
+        List<ITab> tabs = new ArrayList<>(0);
+
+        if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_MODULE_LIST, SyncopeConstants.ROOT_REALM)) {
+            tabs.add(new AbstractTab(new ResourceModel("authModules")) {
+
+                private static final long serialVersionUID = 5211692813425391144L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new AuthModuleDirectoryPanel(panelId, getPageReference());
+                }
+            });
+        }
+
+        if (SyncopeConsoleSession.get().owns(AMEntitlement.CLIENTAPP_LIST, SyncopeConstants.ROOT_REALM)) {
+            tabs.add(new AbstractTab(new ResourceModel("clientApps")) {
+
+                private static final long serialVersionUID = 5211692813425391144L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new AjaxTextFieldPanel(panelId, panelId, Model.of(""));
+                }
+            });
+        }
+
+        tabs.add(new AbstractTab(Model.of("SAML 2.0 IdP")) {
+
+            private static final long serialVersionUID = 5211692813425391144L;
+
+            @Override
+            public Panel getPanel(final String panelId) {
+                return new AjaxTextFieldPanel(panelId, panelId, Model.of(""));
+            }
+        });
+
+        tabs.add(new AbstractTab(Model.of("OIDC 1.0 Provider")) {
+
+            private static final long serialVersionUID = 5211692813425391144L;
+
+            @Override
+            public Panel getPanel(final String panelId) {
+                return new AjaxTextFieldPanel(panelId, panelId, Model.of(""));
+            }
+        });
+
+        if (SyncopeConsoleSession.get().owns(AMEntitlement.WA_CONFIG_LIST, SyncopeConstants.ROOT_REALM)) {
+            tabs.add(new AbstractTab(new ResourceModel("config")) {
+
+                private static final long serialVersionUID = 5211692813425391144L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new WAConfigDirectoryPanel(panelId, getPageReference());
+                }
+            });
+        }
+
+        if (SyncopeConsoleSession.get().owns(AMEntitlement.AUTH_PROFILE_LIST, SyncopeConstants.ROOT_REALM)) {
+            tabs.add(new AbstractTab(new ResourceModel("authProfiles")) {
+
+                private static final long serialVersionUID = 5211692813425391144L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new AjaxTextFieldPanel(panelId, panelId, Model.of(""));
+                }
+            });
+        }
+
+        List<NetworkService> instances = serviceOps.list(NetworkService.Type.WA);
+        if (!instances.isEmpty()) {
+            tabs.add(new AbstractTab(new ResourceModel("sessions")) {
+
+                private static final long serialVersionUID = 5211692813425391144L;
+
+                @Override
+                public Panel getPanel(final String panelId) {
+                    return new AjaxTextFieldPanel(panelId, panelId, Model.of(instances.get(0).getAddress()));
+                }
+            });
+        }
+
+        return tabs;
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel.java
new file mode 100644
index 0000000..ea5683e
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.panels;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.AMConstants;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.AuthModuleDirectoryPanel.AuthModuleProvider;
+import org.apache.syncope.client.console.rest.AuthModuleRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.client.console.wizards.AuthModuleWizardBuilder;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.DirectoryDataProvider;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.to.AuthModuleTO;
+import org.apache.syncope.common.lib.types.AMEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class AuthModuleDirectoryPanel
+        extends DirectoryPanel<AuthModuleTO, AuthModuleTO, AuthModuleProvider, AuthModuleRestClient> {
+
+    @SpringBean
+    private ClassPathScanImplementationLookup lookup;
+
+    public AuthModuleDirectoryPanel(final String id, final PageReference pageRef) {
+        super(id, pageRef);
+
+        disableCheckBoxes();
+
+        this.addNewItemPanelBuilder(new AuthModuleWizardBuilder(lookup, new AuthModuleTO(), pageRef), true);
+
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, AMEntitlement.AUTH_MODULE_CREATE);
+
+        modal.size(Modal.Size.Extra_large);
+        initResultTable();
+    }
+
+    @Override
+    protected AuthModuleProvider dataProvider() {
+        return new AuthModuleProvider(rows);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return AMConstants.PREF_AUTHMODULE_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBatches() {
+        return List.of();
+    }
+
+    @Override
+    protected List<IColumn<AuthModuleTO, String>> getColumns() {
+        final List<IColumn<AuthModuleTO, String>> columns = new ArrayList<>();
+        columns.add(new PropertyColumn<>(
+                new StringResourceModel(Constants.KEY_FIELD_NAME, this),
+                Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME));
+        columns.add(new PropertyColumn<>(new ResourceModel("description"), "description", "description"));
+        columns.add(new PropertyColumn<AuthModuleTO, String>(new ResourceModel("type"), "conf") {
+
+            private static final long serialVersionUID = -1822504503325964706L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<AuthModuleTO>> item,
+                    final String componentId,
+                    final IModel<AuthModuleTO> rowModel) {
+
+                item.add(new Label(componentId, rowModel.getObject().getConf() == null
+                        ? StringUtils.EMPTY
+                        : StringUtils.substringBefore(
+                                rowModel.getObject().getConf().getClass().getSimpleName(), "AuthModuleConf")));
+            }
+        });
+        return columns;
+    }
+
+    @Override
+    public ActionsPanel<AuthModuleTO> getActions(final IModel<AuthModuleTO> model) {
+        ActionsPanel<AuthModuleTO> panel = super.getActions(model);
+
+        panel.add(new ActionLink<AuthModuleTO>() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target, final AuthModuleTO ignore) {
+                send(AuthModuleDirectoryPanel.this, Broadcast.EXACT, new AjaxWizard.EditItemActionEvent<>(
+                        AuthModuleRestClient.read(model.getObject().getKey()), target));
+            }
+        }, ActionLink.ActionType.EDIT, AMEntitlement.AUTH_MODULE_UPDATE);
+
+        panel.add(new ActionLink<AuthModuleTO>() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target, final AuthModuleTO ignore) {
+                try {
+                    AuthModuleRestClient.delete(model.getObject().getKey());
+
+                    SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+                    target.add(container);
+                } catch (Exception e) {
+                    LOG.error("While deleting {}", model.getObject().getKey(), e);
+                    SyncopeConsoleSession.get().onException(e);
+                }
+                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+            }
+        }, ActionLink.ActionType.DELETE, AMEntitlement.AUTH_MODULE_DELETE, true);
+
+        return panel;
+    }
+
+    protected static final class AuthModuleProvider extends DirectoryDataProvider<AuthModuleTO> {
+
+        private static final long serialVersionUID = -185944053385660794L;
+
+        private final SortableDataProviderComparator<AuthModuleTO> comparator;
+
+        private AuthModuleProvider(final int paginatorRows) {
+            super(paginatorRows);
+            setSort(Constants.KEY_FIELD_NAME, SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        @Override
+        public Iterator<AuthModuleTO> iterator(final long first, final long count) {
+            List<AuthModuleTO> result = AuthModuleRestClient.list();
+            result.sort(comparator);
+            return result.subList((int) first, (int) first + (int) count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return AuthModuleRestClient.list().size();
+        }
+
+        @Override
+        public IModel<AuthModuleTO> model(final AuthModuleTO object) {
+            return new CompoundPropertyModel<>(object);
+        }
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java
index 3c210bf..183c0f4 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SRARouteDirectoryPanel.java
@@ -40,10 +40,8 @@ import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.SRARouteTO;
 import org.apache.syncope.common.lib.types.AMEntitlement;
-import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
@@ -73,28 +71,6 @@ public class SRARouteDirectoryPanel
 
         addNewItemPanelBuilder(new SRARouteWizardBuilder(new SRARouteTO(), pageRef), true);
         initResultTable();
-
-        utilityAjaxLink = new AjaxLink<SRARouteTO>("utility") {
-
-            private static final long serialVersionUID = -7978723352517770644L;
-
-            @Override
-            public void onClick(final AjaxRequestTarget target) {
-                try {
-                    SRARouteRestClient.push();
-                    SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
-                    target.add(container);
-                } catch (Exception e) {
-                    LOG.error("While pushing to SRA", e);
-                    SyncopeConsoleSession.get().onException(e);
-                }
-                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
-            }
-        };
-        initialFragment.addOrReplace(utilityAjaxLink);
-        utilityAjaxLink.add(utilityIcon);
-        utilityIcon.add(new AttributeModifier("class", "fa fa-fast-forward"));
-        enableUtilityButton();
     }
 
     @Override
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel.java
similarity index 58%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
copy to client/am/console/src/main/java/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel.java
index 4993f6b..7bbe336 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel.java
@@ -21,25 +21,24 @@ package org.apache.syncope.client.console.panels;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.stream.Collectors;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.DirectoryDataProvider;
-import org.apache.syncope.client.console.commons.IdRepoConstants;
+import org.apache.syncope.client.console.commons.AMConstants;
 import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
 import org.apache.syncope.client.console.pages.BasePage;
-import org.apache.syncope.client.console.panels.ParametersDirectoryPanel.ParametersProvider;
-import org.apache.syncope.client.console.rest.SyncopeRestClient;
+import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel.WAConfigProvider;
+import org.apache.syncope.client.console.rest.WAConfigRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.DirectoryDataProvider;
 import org.apache.syncope.client.ui.commons.panels.WizardModalPanel;
-import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
+import org.apache.syncope.client.ui.commons.wizards.AbstractModalPanelBuilder;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.lib.types.AMEntitlement;
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -53,23 +52,19 @@ import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.spring.injection.annot.SpringBean;
-
-public class ParametersDirectoryPanel
-        extends DirectoryPanel<ConfParam, ConfParam, ParametersProvider, SyncopeRestClient> {
 
-    private static final long serialVersionUID = 2765863608539154422L;
+public class WAConfigDirectoryPanel
+        extends DirectoryPanel<Attr, Attr, WAConfigProvider, WAConfigRestClient> {
 
-    @SpringBean
-    private ConfParamOps confParamOps;
+    private static final long serialVersionUID = 1538796157345L;
 
-    public ParametersDirectoryPanel(final String id, final PageReference pageRef) {
-        super(id, new Builder<ConfParam, ConfParam, SyncopeRestClient>(new SyncopeRestClient(), pageRef) {
+    public WAConfigDirectoryPanel(final String id, final PageReference pageRef) {
+        super(id, new Builder<Attr, Attr, WAConfigRestClient>(new WAConfigRestClient(), pageRef) {
 
             private static final long serialVersionUID = 8769126634538601689L;
 
             @Override
-            protected WizardMgtPanel<ConfParam> newInstance(final String id, final boolean wizardInModal) {
+            protected WizardMgtPanel<Attr> newInstance(final String id, final boolean wizardInModal) {
                 throw new UnsupportedOperationException();
             }
         });
@@ -77,53 +72,48 @@ public class ParametersDirectoryPanel
         itemKeyFieldName = "schema";
         disableCheckBoxes();
 
-        this.addNewItemPanelBuilder(new AbstractModalPanelBuilder<ConfParam>(new ConfParam(), pageRef) {
+        this.addNewItemPanelBuilder(new AbstractModalPanelBuilder<Attr>(new Attr(), pageRef) {
 
             private static final long serialVersionUID = 1995192603527154740L;
 
             @Override
-            public WizardModalPanel<ConfParam> build(
-                    final String id, final int index, final AjaxWizard.Mode mode) {
-
-                return new ParametersModalPanel(modal, newModelObject(), confParamOps, mode, pageRef);
+            public WizardModalPanel<Attr> build(final String id, final int index, final AjaxWizard.Mode mode) {
+                return new WAConfigModalPanel(modal, newModelObject(), mode, pageRef);
             }
         }, true);
+
         modal.size(Modal.Size.Default);
         initResultTable();
     }
 
-    public ParametersDirectoryPanel(final String id, final Builder<ConfParam, ConfParam, SyncopeRestClient> builder) {
-        super(id, builder);
-    }
-
     @Override
-    protected ParametersProvider dataProvider() {
-        return new ParametersProvider(rows);
+    protected WAConfigProvider dataProvider() {
+        return new WAConfigProvider(rows);
     }
 
     @Override
     protected String paginatorRowsKey() {
-        return IdRepoConstants.PREF_PARAMETERS_PAGINATOR_ROWS;
+        return AMConstants.PREF_WACONFIG_PAGINATOR_ROWS;
     }
 
     @Override
     protected Collection<ActionLink.ActionType> getBatches() {
-        return Collections.<ActionLink.ActionType>singletonList(ActionLink.ActionType.DELETE);
+        return List.of();
     }
 
     @Override
-    protected List<IColumn<ConfParam, String>> getColumns() {
-        final List<IColumn<ConfParam, String>> columns = new ArrayList<>();
+    protected List<IColumn<Attr, String>> getColumns() {
+        final List<IColumn<Attr, String>> columns = new ArrayList<>();
         columns.add(new PropertyColumn<>(new ResourceModel("schema"), "schema"));
-        columns.add(new PropertyColumn<ConfParam, String>(new ResourceModel("values"), "values") {
+        columns.add(new PropertyColumn<Attr, String>(new ResourceModel("values"), "values") {
 
             private static final long serialVersionUID = -1822504503325964706L;
 
             @Override
             public void populateItem(
-                    final Item<ICellPopulator<ConfParam>> item,
+                    final Item<ICellPopulator<Attr>> item,
                     final String componentId,
-                    final IModel<ConfParam> rowModel) {
+                    final IModel<Attr> rowModel) {
 
                 if (rowModel.getObject().getValues().toString().length() > 96) {
                     item.add(new Label(componentId, getString("tooLong")).
@@ -137,80 +127,70 @@ public class ParametersDirectoryPanel
     }
 
     @Override
-    public ActionsPanel<ConfParam> getActions(final IModel<ConfParam> model) {
-        final ActionsPanel<ConfParam> panel = super.getActions(model);
+    public ActionsPanel<Attr> getActions(final IModel<Attr> model) {
+        ActionsPanel<Attr> panel = super.getActions(model);
 
-        panel.add(new ActionLink<ConfParam>() {
+        panel.add(new ActionLink<Attr>() {
 
             private static final long serialVersionUID = -3722207913631435501L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final ConfParam ignore) {
+            public void onClick(final AjaxRequestTarget target, final Attr ignore) {
                 target.add(modal);
-                // modal.addSubmitButton();
                 modal.header(new StringResourceModel("any.edit"));
-                modal.setContent(new ParametersModalPanel(
-                        modal, model.getObject(), confParamOps, AjaxWizard.Mode.EDIT, pageRef));
+                modal.setContent(new WAConfigModalPanel(modal, model.getObject(), AjaxWizard.Mode.EDIT, pageRef));
                 modal.show(true);
             }
-        }, ActionLink.ActionType.EDIT, null);
+        }, ActionLink.ActionType.EDIT, AMEntitlement.WA_CONFIG_SET);
 
-        panel.add(new ActionLink<ConfParam>() {
+        panel.add(new ActionLink<Attr>() {
 
             private static final long serialVersionUID = -3722207913631435501L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target, final ConfParam ignore) {
+            public void onClick(final AjaxRequestTarget target, final Attr ignore) {
                 try {
-                    confParamOps.remove(SyncopeConsoleSession.get().getDomain(), model.getObject().getSchema());
+                    WAConfigRestClient.delete(model.getObject().getSchema());
 
                     SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
                     target.add(container);
                 } catch (Exception e) {
-                    LOG.error("While deleting {}", model.getObject(), e);
+                    LOG.error("While deleting {}", model.getObject().getSchema(), e);
                     SyncopeConsoleSession.get().onException(e);
                 }
                 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
             }
-        }, ActionLink.ActionType.DELETE, null, true);
+        }, ActionLink.ActionType.DELETE, AMEntitlement.WA_CONFIG_DELETE, true);
 
         return panel;
     }
 
-    protected final class ParametersProvider extends DirectoryDataProvider<ConfParam> {
+    protected static final class WAConfigProvider extends DirectoryDataProvider<Attr> {
 
         private static final long serialVersionUID = -185944053385660794L;
 
-        private final SortableDataProviderComparator<ConfParam> comparator;
+        private final SortableDataProviderComparator<Attr> comparator;
 
-        private ParametersProvider(final int paginatorRows) {
+        private WAConfigProvider(final int paginatorRows) {
             super(paginatorRows);
             setSort("schema", SortOrder.ASCENDING);
             comparator = new SortableDataProviderComparator<>(this);
         }
 
         @Override
-        public Iterator<ConfParam> iterator(final long first, final long count) {
-            List<ConfParam> list = confParamOps.list(SyncopeConsoleSession.get().getDomain()).entrySet().stream().
-                    skip(first).limit(count).
-                    map(entry -> {
-                        ConfParam param = new ConfParam();
-                        param.setSchema(entry.getKey());
-                        param.setValues(entry.getValue());
-                        return param;
-                    }).collect(Collectors.toList());
-
-            list.sort(comparator);
-            return list.iterator();
+        public Iterator<Attr> iterator(final long first, final long count) {
+            List<Attr> result = WAConfigRestClient.list();
+            result.sort(comparator);
+            return result.subList((int) first, (int) first + (int) count).iterator();
         }
 
         @Override
         public long size() {
-            return confParamOps.list(SyncopeConsoleSession.get().getDomain()).size();
+            return WAConfigRestClient.list().size();
         }
 
         @Override
-        public IModel<ConfParam> model(final ConfParam object) {
+        public IModel<Attr> model(final Attr object) {
             return new CompoundPropertyModel<>(object);
         }
     }
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WAConfigModalPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WAConfigModalPanel.java
new file mode 100644
index 0000000..e95f3c9
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/WAConfigModalPanel.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.panels;
+
+import java.io.Serializable;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.rest.WAConfigRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.wizard.WizardModel;
+
+public class WAConfigModalPanel extends AbstractModalPanel<Attr> {
+
+    private static final long serialVersionUID = 1690738212977L;
+
+    private static ConfParam toConfParam(final Attr attr) {
+        ConfParam param = new ConfParam();
+        param.setSchema(attr.getSchema());
+        param.getValues().addAll(attr.getValues());
+        return param;
+    }
+
+    private static Attr toAttr(final ConfParam confParam) {
+        Attr attr = new Attr.Builder(confParam.getSchema()).build();
+        attr.getValues().addAll(
+                confParam.getValues().stream().map(Serializable::toString).collect(Collectors.toList()));
+        return attr;
+    }
+
+    private final ParametersWizardPanel.ParametersForm form;
+
+    public WAConfigModalPanel(
+            final BaseModal<Attr> modal,
+            final Attr attr,
+            final AjaxWizard.Mode mode,
+            final PageReference pageRef) {
+
+        super(modal, pageRef);
+
+        PlainSchemaTO schema = new PlainSchemaTO();
+        schema.setType(AttrSchemaType.String);
+        schema.setMandatoryCondition("true");
+        schema.setMultivalue(false);
+
+        form = new ParametersWizardPanel.ParametersForm(schema, toConfParam(attr));
+
+        add(new ParametersWizardPanel(form, null, pageRef) {
+
+            @Override
+            protected WizardModel buildModelSteps(final ParametersForm modelObject, final WizardModel wizardModel) {
+                wizardModel.add(new ParametersWizardAttrStep(mode, modelObject));
+                return wizardModel;
+            }
+
+            @Override
+            protected Serializable onApplyInternal(final ParametersWizardPanel.ParametersForm modelObject) {
+                modelObject.getParam().setMultivalue(modelObject.getSchema().isMultivalue());
+                try {
+                    WAConfigRestClient.set(toAttr(modelObject.getParam()));
+                } catch (Exception e) {
+                    LOG.error("While setting {}", modelObject.getParam(), e);
+                    throw e;
+                }
+                return modelObject.getParam();
+            }
+        }.build("waConfigWizardPanel", mode));
+    }
+
+    @Override
+    public final Attr getItem() {
+        return toAttr(form.getParam());
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java
new file mode 100644
index 0000000..59ced00
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.policies;
+
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
+import org.apache.syncope.common.lib.types.IdRepoEntitlement;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+
+public class AccessPolicyDirectoryPanel extends PolicyDirectoryPanel<AccessPolicyTO> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    public AccessPolicyDirectoryPanel(final String id, final PageReference pageRef) {
+        super(id, PolicyType.ACCESS, pageRef);
+
+        AccessPolicyTO defaultItem = new AccessPolicyTO();
+
+        this.addNewItemPanelBuilder(
+                new PolicyModalPanelBuilder<>(PolicyType.ACCESS, defaultItem, modal, pageRef), true);
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, IdRepoEntitlement.POLICY_CREATE);
+
+        initResultTable();
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AttrReleasePolicyDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AttrReleasePolicyDirectoryPanel.java
new file mode 100644
index 0000000..9ab9f92
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AttrReleasePolicyDirectoryPanel.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.policies;
+
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
+import org.apache.syncope.common.lib.types.IdRepoEntitlement;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+
+public class AttrReleasePolicyDirectoryPanel extends PolicyDirectoryPanel<AttrReleasePolicyTO> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    public AttrReleasePolicyDirectoryPanel(final String id, final PageReference pageRef) {
+        super(id, PolicyType.ATTR_RELEASE, pageRef);
+
+        AttrReleasePolicyTO defaultItem = new AttrReleasePolicyTO();
+
+        this.addNewItemPanelBuilder(
+                new PolicyModalPanelBuilder<>(PolicyType.ATTR_RELEASE, defaultItem, modal, pageRef), true);
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, IdRepoEntitlement.POLICY_CREATE);
+
+        initResultTable();
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AuthPolicyDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AuthPolicyDirectoryPanel.java
new file mode 100644
index 0000000..be8b36a
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AuthPolicyDirectoryPanel.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.policies;
+
+import org.apache.syncope.common.lib.policy.AuthPolicyTO;
+import org.apache.syncope.common.lib.types.IdRepoEntitlement;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+
+public class AuthPolicyDirectoryPanel extends PolicyDirectoryPanel<AuthPolicyTO> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    public AuthPolicyDirectoryPanel(final String id, final PageReference pageRef) {
+        super(id, PolicyType.AUTH, pageRef);
+
+        AuthPolicyTO defaultItem = new AuthPolicyTO();
+
+        this.addNewItemPanelBuilder(
+                new PolicyModalPanelBuilder<>(PolicyType.AUTH, defaultItem, modal, pageRef), true);
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, IdRepoEntitlement.POLICY_CREATE);
+
+        initResultTable();
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AuthModuleRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AuthModuleRestClient.java
new file mode 100644
index 0000000..29cdcb1
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/AuthModuleRestClient.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.rest;
+
+import java.util.List;
+import org.apache.syncope.common.lib.to.AuthModuleTO;
+import org.apache.syncope.common.rest.api.service.AuthModuleService;
+
+public class AuthModuleRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -7379778542101161274L;
+
+    public static List<AuthModuleTO> list() {
+        return getService(AuthModuleService.class).list();
+    }
+
+    public static void create(final AuthModuleTO authModuleTO) {
+        getService(AuthModuleService.class).create(authModuleTO);
+    }
+
+    public static AuthModuleTO read(final String key) {
+        return getService(AuthModuleService.class).read(key);
+    }
+
+    public static void update(final AuthModuleTO authModuleTO) {
+        getService(AuthModuleService.class).update(authModuleTO);
+    }
+
+    public static void delete(final String key) {
+        getService(AuthModuleService.class).delete(key);
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WAConfigRestClient.java
similarity index 54%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
copy to client/am/console/src/main/java/org/apache/syncope/client/console/rest/WAConfigRestClient.java
index 05882c5..8b683ea 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/WAConfigRestClient.java
@@ -16,15 +16,29 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.commons;
+package org.apache.syncope.client.console.rest;
 
-import java.io.Serializable;
 import java.util.List;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.syncope.common.lib.Attr;
+import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
 
-@FunctionalInterface
-public interface PolicyTabProvider extends Serializable {
+public class WAConfigRestClient extends BaseRestClient {
 
-    List<ITab> buildTabList(PageReference pageRef);
+    private static final long serialVersionUID = -7379778542101161274L;
+
+    public static List<Attr> list() {
+        return getService(WAConfigService.class).list();
+    }
+
+    public static void set(final Attr value) {
+        getService(WAConfigService.class).set(value);
+    }
+
+    public static void delete(final String schema) {
+        getService(WAConfigService.class).delete(schema);
+    }
+
+    public static void push() {
+        getService(WAConfigService.class).pushToWA();
+    }
 }
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java
new file mode 100644
index 0000000..b71bc2e
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.wizards;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.panels.BeanPanel;
+import org.apache.syncope.client.console.rest.AuthModuleRestClient;
+import org.apache.syncope.client.console.wizards.mapping.AuthModuleMappingPanel;
+import org.apache.syncope.client.ui.commons.Constants;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.auth.AuthModuleConf;
+import org.apache.syncope.common.lib.to.AuthModuleTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.springframework.util.ClassUtils;
+
+public class AuthModuleWizardBuilder extends BaseAjaxWizardBuilder<AuthModuleTO> {
+
+    private final LoadableDetachableModel<List<String>> authModuleConfs;
+
+    public AuthModuleWizardBuilder(
+            final ClassPathScanImplementationLookup lookup,
+            final AuthModuleTO defaultItem,
+            final PageReference pageRef) {
+
+        super(defaultItem, pageRef);
+
+        authModuleConfs = new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return lookup.getClasses(AuthModuleConf.class).stream().
+                        map(Class::getName).sorted().collect(Collectors.toList());
+            }
+        };
+    }
+
+    @Override
+    protected Serializable onApplyInternal(final AuthModuleTO modelObject) {
+        if (mode == AjaxWizard.Mode.CREATE) {
+            AuthModuleRestClient.create(modelObject);
+        } else {
+            AuthModuleRestClient.update(modelObject);
+        }
+        return modelObject;
+    }
+
+    @Override
+    protected WizardModel buildModelSteps(final AuthModuleTO modelObject, final WizardModel wizardModel) {
+        wizardModel.add(new Profile(modelObject, authModuleConfs));
+        wizardModel.add(new Configuration(modelObject));
+        wizardModel.add(new Mapping(modelObject));
+        return wizardModel;
+    }
+
+    public static class Profile extends WizardStep {
+
+        private static final long serialVersionUID = -3043839139187792810L;
+
+        Profile(final AuthModuleTO authModule, final LoadableDetachableModel<List<String>> authModuleConfs) {
+            boolean isNew = authModule.getConf() == null;
+
+            AjaxTextFieldPanel key = new AjaxTextFieldPanel(
+                    Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME,
+                    new PropertyModel<>(authModule, Constants.KEY_FIELD_NAME));
+            key.addRequiredLabel();
+            key.setEnabled(isNew);
+            add(key);
+
+            AjaxTextFieldPanel description = new AjaxTextFieldPanel(
+                    "description", getString("description"), new PropertyModel<>(authModule, "description"));
+            add(description);
+
+            AjaxDropDownChoicePanel<String> conf = new AjaxDropDownChoicePanel<>("conf", getString("type"), isNew
+                    ? Model.of()
+                    : Model.of(authModule.getConf().getClass().getName()));
+            conf.setChoices(authModuleConfs.getObject());
+            conf.addRequiredLabel();
+            conf.setNullValid(false);
+            conf.setEnabled(isNew);
+            conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -7133385027739964990L;
+
+                @SuppressWarnings("unchecked")
+                @Override
+                protected void onEvent(final AjaxRequestTarget target) {
+                    try {
+                        Class<? extends AuthModuleConf> authModuleConfClass =
+                                (Class<? extends AuthModuleConf>) ClassUtils.resolveClassName(
+                                        conf.getModelObject(), ClassUtils.getDefaultClassLoader());
+
+                        authModule.setConf(authModuleConfClass.getConstructor().newInstance());
+                    } catch (Exception e) {
+                        LOG.error("During deserialization", e);
+                    }
+                }
+            });
+            add(conf);
+        }
+    }
+
+    public static class Configuration extends WizardStep {
+
+        private static final long serialVersionUID = -785981096328637758L;
+
+        Configuration(final AuthModuleTO authModule) {
+            add(new BeanPanel<>("bean", new PropertyModel<>(authModule, "conf")).setRenderBodyOnly(true));
+        }
+    }
+
+    private static final class Mapping extends WizardStep {
+
+        private static final long serialVersionUID = 3454904947720856253L;
+
+        Mapping(final AuthModuleTO authModule) {
+            setTitleModel(Model.of("Mapping"));
+            setSummaryModel(Model.of(StringUtils.EMPTY));
+            add(new AuthModuleMappingPanel("mapping", authModule));
+        }
+    }
+}
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AuthModuleMappingPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AuthModuleMappingPanel.java
new file mode 100644
index 0000000..0e1af8c
--- /dev/null
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AuthModuleMappingPanel.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.wizards.mapping;
+
+import java.util.List;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.to.AuthModuleTO;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+public class AuthModuleMappingPanel extends AbstractMappingPanel {
+
+    public AuthModuleMappingPanel(final String id, final AuthModuleTO authModule) {
+        super(id,
+                null,
+                null,
+                new ListModel<>(authModule.getItems()),
+                true,
+                MappingPurpose.NONE);
+
+        setOutputMarkupId(true);
+    }
+
+    @Override
+    protected void onBeforeRender() {
+        super.onBeforeRender();
+        intAttrNameInfo.setVisible(false);
+    }
+
+    @Override
+    protected boolean hidePurpose() {
+        return true;
+    }
+
+    @Override
+    protected boolean hideMandatory() {
+        return true;
+    }
+
+    @Override
+    protected boolean hideConnObjectKey() {
+        return true;
+    }
+
+    @Override
+    protected IModel<List<String>> getExtAttrNames() {
+        return Model.ofList(List.of());
+    }
+
+    @Override
+    protected void setAttrNames(final AjaxTextFieldPanel toBeUpdated) {
+        // nothing to do
+    }
+}
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html
index f42ca2c..ce74d32 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html
@@ -22,7 +22,9 @@ under the License.
       <div class="container-fluid">
         <div class="row mb-2">
           <div class="col-sm-6">
-            <h1>&nbsp;</h1>
+            <button class="btn btn-success" wicket:id="push">
+              <span class="fa fa-fast-forward"></span> <wicket:message key="push"/>
+            </button>
           </div>
           <div class="col-sm-6">
             <ol class="breadcrumb float-sm-right">
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
index 7e7ef61..bfb4155 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
@@ -28,3 +28,4 @@ logout=Logout
 csrf=CSRF
 error=Error URI
 postLogout=Post-logout URI
+push=Push
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_fr_CA.properties
similarity index 99%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_fr_CA.properties
index 7e7ef61..bfb4155 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_fr_CA.properties
@@ -28,3 +28,4 @@ logout=Logout
 csrf=CSRF
 error=Error URI
 postLogout=Post-logout URI
+push=Push
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_it.properties
index ee54f92..ebb61e6 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_it.properties
@@ -28,3 +28,4 @@ logout=Logout
 csrf=CSRF
 error=URI di errore
 postLogout=URI di post-logout
+push=Applica
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ja.properties
index 6871cb3..fd47c1e 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ja.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ja.properties
@@ -28,3 +28,4 @@ logout=Logout
 csrf=CSRF
 error=Error URI
 postLogout=Post-logout URI
+push=Push
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_pt_BR.properties
index 7e7ef61..bfb4155 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_pt_BR.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_pt_BR.properties
@@ -28,3 +28,4 @@ logout=Logout
 csrf=CSRF
 error=Error URI
 postLogout=Post-logout URI
+push=Push
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ru.properties
index 7e7ef61..bfb4155 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ru.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA_ru.properties
@@ -28,3 +28,4 @@ logout=Logout
 csrf=CSRF
 error=Error URI
 postLogout=Post-logout URI
+push=Push
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.html
similarity index 90%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.html
index f42ca2c..a0f621f 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.html
@@ -22,14 +22,16 @@ under the License.
       <div class="container-fluid">
         <div class="row mb-2">
           <div class="col-sm-6">
-            <h1>&nbsp;</h1>
+            <button class="btn btn-success" wicket:id="push">
+              <span class="fa fa-fast-forward"></span> <wicket:message key="push"/>
+            </button>
           </div>
           <div class="col-sm-6">
             <ol class="breadcrumb float-sm-right">
               <li class="breadcrumb-item">
                 <a wicket:id="dashboardBr"><i class="fa fa-tachometer-alt"></i> <wicket:message key="dashboard"></wicket:message></a>
               </li>
-              <li class="breadcrumb-item active"><wicket:message key="sra"/></li>
+              <li class="breadcrumb-item active"><wicket:message key="wa"/></li>
             </ol>
           </div>
         </div>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties
index b8dd372..4b5a308 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties
@@ -14,7 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+wa=WA
+authModules=Authentication Modules
+clientApps=Client Applications
+config=Parameters
+sessions=Sessions
+authProfiles=Profiles
+push=Push
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties
index b8dd372..4b5a308 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties
@@ -14,7 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+wa=WA
+authModules=Authentication Modules
+clientApps=Client Applications
+config=Parameters
+sessions=Sessions
+authProfiles=Profiles
+push=Push
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties
index b8dd372..e27e0cd 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties
@@ -14,7 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+wa=WA
+authModules=Moduli di Autenticazione
+clientApps=Applicazioni Client
+config=Parametri
+sessions=Sessioni
+authProfiles=Profili
+push=Applica
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties
index b8dd372..4b5a308 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties
@@ -14,7 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+wa=WA
+authModules=Authentication Modules
+clientApps=Client Applications
+config=Parameters
+sessions=Sessions
+authProfiles=Profiles
+push=Push
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties
index b8dd372..4b5a308 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties
@@ -14,7 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+wa=WA
+authModules=Authentication Modules
+clientApps=Client Applications
+config=Parameters
+sessions=Sessions
+authProfiles=Profiles
+push=Push
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties
index b8dd372..4b5a308 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties
@@ -14,7 +14,10 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+wa=WA
+authModules=Authentication Modules
+clientApps=Client Applications
+config=Parameters
+sessions=Sessions
+authProfiles=Profiles
+push=Push
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel.properties
similarity index 87%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel.properties
index b8dd372..9b5b243 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel.properties
@@ -14,7 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Edit Parameter ${key}
+any.new=New Auth Module
+any.edit=Edit Auth Module
+description=Description
+type=Type
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_fr_CA.properties
similarity index 86%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_fr_CA.properties
index b8dd372..d7674d0 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_fr_CA.properties
@@ -14,7 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Modifier param\u00e8tre ${key}
+any.new=New Auth Module
+any.edit=Edit Auth Module
+description=Description
+type=Type
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_it.properties
similarity index 83%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_it.properties
index b8dd372..117bd05 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_it.properties
@@ -14,7 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Modifica parametro ${key}
+any.new=Nuovo Modulo di Autenticazione
+any.edit=Aggiorna Modulo di Autenticazione
+description=Descrizione
+type=Tipo
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_ja.properties
similarity index 83%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_ja.properties
index b8dd372..d8622d8 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_ja.properties
@@ -14,7 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc ${key} \u3092\u7de8\u96c6
+any.new=New Auth Module
+any.edit=Edit Auth Module
+description=Description
+type=Type
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_pt_BR.properties
similarity index 87%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_pt_BR.properties
index b8dd372..3ba3742 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_pt_BR.properties
@@ -14,7 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Editar par\u00e2metro
+any.new=New Auth Module
+any.edit=Edit Auth Module
+description=Description
+type=Type
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_ru.properties
new file mode 100644
index 0000000..3fcebae
--- /dev/null
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/AuthModuleDirectoryPanel_ru.properties
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+# any.edit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00bf\u00d0\u00b0\u00d1\u0080\u00d0\u00b0\u00d0\u00bc\u00d0\u00b5\u00d1\u0082\u00d1\u0080 ${key}
+any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 ${key}
+# any.new=\u00d0\u00a1\u00d0\u00be\u00d0\u00b7\u00d0\u00b4\u00d0\u00b0\u00d1\u0082\u00d1\u008c \u00d0\u00bf\u00d0\u00b0\u00d1\u0080\u00d0\u00b0\u00d0\u00bc\u00d0\u00b5\u00d1\u0082\u00d1\u0080
+any.new=New Auth Module
+# any.edit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00bf\u00d0\u00b0\u00d1\u0080\u00d0\u00b0\u00d0\u00bc\u00d0\u00b5\u00d1\u0082\u00d1\u0080
+any.edit=Edit Auth Module
+description=Description
+type=Type
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel.properties
similarity index 84%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel.properties
index b8dd372..b4dd675 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel.properties
@@ -14,7 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Edit Parameter ${key}
+any.new=New Parameter
+values=Values
+readonly=Readonly
+any.edit=Edit parameter
+tooLong=Value too long to be displayed
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_fr_CA.properties
similarity index 85%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_fr_CA.properties
index a0b9e8a..788dbfd 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_fr_CA.properties
@@ -14,8 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-any.edit=Modifier param�tre ${key}
-any.new=Nouveau param�tre
+any.edit=Modifier param\u00e8tre ${key}
+any.new=Nouveau param\u00e8tre
 values=Valeurs
 readonly=Lecture seulement
-any.edit=Modifier param�tre
+any.edit=Modifier param\u00e8tre
+tooLong=Value too long to be displayed
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_it.properties
similarity index 82%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_it.properties
index b8dd372..2c0a04f 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_it.properties
@@ -14,7 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Modifica parametro ${key}
+any.new=Nuovo parametro
+values=Valori
+readonly=Readonly
+any.edit=Aggiorna parametro
+tooLong=Valore troppo lungo per essere mostrato
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_ja.properties
similarity index 69%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_ja.properties
index 7e7ef61..5b0c340 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_ja.properties
@@ -14,17 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-sra=SRA
-routes=Routes
-metrics=Metrics
-order=Order
-target=Target
-type=Type
-any.new=New gateway route
-any.edit=Edit ${name}
-predicates=Predicates
-filters=Filters
-logout=Logout
-csrf=CSRF
-error=Error URI
-postLogout=Post-logout URI
+any.edit=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc ${key} \u3092\u7de8\u96c6
+any.new=\u65b0\u3057\u3044\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc
+values=\u5024
+readonly=\u8aad\u307f\u53d6\u308a\u5c02\u7528
+any.edit=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3092\u7de8\u96c6
+tooLong=\u5024\u304c\u9577\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u307e\u305b\u3093
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_pt_BR.properties
similarity index 82%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_pt_BR.properties
index b8dd372..017cf2a 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_pt_BR.properties
@@ -14,7 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+any.edit=Editar par\u00e2metro
+any.new=Novo par\u00e2metro
+values=Valores
+readonly=Somente Leitura
+any.edit=Editar par\u00e2metro
+tooLong=Value too long to be displayed
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_ru.properties
new file mode 100644
index 0000000..d550995
--- /dev/null
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigDirectoryPanel_ru.properties
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+# any.edit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00bf\u00d0\u00b0\u00d1\u0080\u00d0\u00b0\u00d0\u00bc\u00d0\u00b5\u00d1\u0082\u00d1\u0080 ${key}
+any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 ${key}
+# any.new=\u00d0\u00a1\u00d0\u00be\u00d0\u00b7\u00d0\u00b4\u00d0\u00b0\u00d1\u0082\u00d1\u008c \u00d0\u00bf\u00d0\u00b0\u00d1\u0080\u00d0\u00b0\u00d0\u00bc\u00d0\u00b5\u00d1\u0082\u00d1\u0080
+any.new=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440
+# values=\u00d0\u0097\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
+values=\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f
+# readonly=\u00d0\u00a2\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00ba\u00d0\u00be \u00d1\u0087\u00d1\u0082\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
+readonly=\u0422\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u0435\u043d\u0438\u0435
+# any.edit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00bf\u00d0\u00b0\u00d1\u0080\u00d0\u00b0\u00d0\u00bc\u00d0\u00b5\u00d1\u0082\u00d1\u0080
+any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440
+tooLong=Value too long to be displayed
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigModalPanel.html
similarity index 92%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigModalPanel.html
index 6f94ce5..83d370f 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/WAConfigModalPanel.html
@@ -18,6 +18,6 @@ under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:extend>
-    <div wicket:id="parametersDetailsPanel">[parametersDetailsPanel]</div>
+    <div wicket:id="waConfigWizardPanel">[waConfigWizardPanel]</div>
   </wicket:extend>
 </html>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration.html
similarity index 88%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration.html
index 6f94ce5..7772c93 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration.html
@@ -17,7 +17,7 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <wicket:extend>
-    <div wicket:id="parametersDetailsPanel">[parametersDetailsPanel]</div>
-  </wicket:extend>
+  <wicket:panel>
+    <span wicket:id="bean"/>
+  </wicket:panel>
 </html>
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration.properties
similarity index 74%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration.properties
index 7e7ef61..8d2c500 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration.properties
@@ -14,17 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-sra=SRA
-routes=Routes
-metrics=Metrics
-order=Order
-target=Target
-type=Type
-any.new=New gateway route
-any.edit=Edit ${name}
-predicates=Predicates
-filters=Filters
-logout=Logout
-csrf=CSRF
-error=Error URI
-postLogout=Post-logout URI
+plainAttrs=Plain Attributes
+derAttrs=Derived Attributes
+virAttrs=Virtual Attributes
+features=Features
+matchingCond=Matching Condition
+userMatchingCond=User Matching Condition
+groupMatchingCond=Group Matching Condition
+anyObjectMatchingCond=AnyObject Matching Condition
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_fr_CA.properties
similarity index 70%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_fr_CA.properties
index 7e7ef61..e791574 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_fr_CA.properties
@@ -14,17 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-sra=SRA
-routes=Routes
-metrics=Metrics
-order=Order
-target=Target
-type=Type
-any.new=New gateway route
-any.edit=Edit ${name}
-predicates=Predicates
-filters=Filters
-logout=Logout
-csrf=CSRF
-error=Error URI
-postLogout=Post-logout URI
+plainAttrs=Attributs simples
+derAttrs=Attributs d�riv�s
+virAttrs=Attributs virtuels
+features=Caract�ristiques
+matchingCond=Condition d'appariement
+userMatchingCond=Condition d'appariement des utilisateurs
+groupMatchingCond=Condition d'appariement de groupe
+anyObjectMatchingCond=Condition d'appariement de n'importe quel objet
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_it.properties
similarity index 74%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_it.properties
index 7e7ef61..6688f85 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_it.properties
@@ -14,17 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-sra=SRA
-routes=Routes
-metrics=Metrics
-order=Order
-target=Target
-type=Type
-any.new=New gateway route
-any.edit=Edit ${name}
-predicates=Predicates
-filters=Filters
-logout=Logout
-csrf=CSRF
-error=Error URI
-postLogout=Post-logout URI
+plainAttrs=Attributi
+derAttrs=Attributi Derivati
+virAttrs=Attributi Virtuali
+features=Features
+matchingCond=Condizione di matching
+userMatchingCond=Condizione di matching utente
+groupMatchingCond=Condizione di matching gruppo
+anyObjectMatchingCond=Condizione di matching any
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_ja.properties
similarity index 66%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_ja.properties
index 7e7ef61..ba85e50 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_ja.properties
@@ -14,17 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-sra=SRA
-routes=Routes
-metrics=Metrics
-order=Order
-target=Target
-type=Type
-any.new=New gateway route
-any.edit=Edit ${name}
-predicates=Predicates
-filters=Filters
-logout=Logout
-csrf=CSRF
-error=Error URI
-postLogout=Post-logout URI
+plainAttrs=\u30d7\u30ec\u30fc\u30f3\u5c5e\u6027
+derAttrs=\u6d3e\u751f\u5c5e\u6027
+virAttrs=\u4eee\u60f3\u5c5e\u6027
+features=\u6a5f\u80fd
+matchingCond=\u4e00\u81f4\u6761\u4ef6
+userMatchingCond=\u30e6\u30fc\u30b6\u2015\u4e00\u81f4\u6761\u4ef6
+groupMatchingCond=\u30b0\u30eb\u30fc\u30d7\u4e00\u81f4\u6761\u4ef6
+anyObjectMatchingCond=\u4efb\u610f\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u4e00\u81f4\u6761\u4ef6
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_pt_BR.properties
similarity index 74%
copy from client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_pt_BR.properties
index 7e7ef61..8d2c500 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/SRA.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_pt_BR.properties
@@ -14,17 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-sra=SRA
-routes=Routes
-metrics=Metrics
-order=Order
-target=Target
-type=Type
-any.new=New gateway route
-any.edit=Edit ${name}
-predicates=Predicates
-filters=Filters
-logout=Logout
-csrf=CSRF
-error=Error URI
-postLogout=Post-logout URI
+plainAttrs=Plain Attributes
+derAttrs=Derived Attributes
+virAttrs=Virtual Attributes
+features=Features
+matchingCond=Matching Condition
+userMatchingCond=User Matching Condition
+groupMatchingCond=Group Matching Condition
+anyObjectMatchingCond=AnyObject Matching Condition
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_ru.properties
new file mode 100644
index 0000000..721b3e5
--- /dev/null
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Configuration_ru.properties
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+plainAttrs=\u041f\u0440\u043e\u0441\u0442\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
+derAttrs=\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
+virAttrs=\u0412\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
+features=\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430
+matchingCond=\u041a\u0440\u0438\u0442\u0435\u0440\u0438\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f
+userMatchingCond=\u041a\u0440\u0438\u0442\u0435\u0440\u0438\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+groupMatchingCond=\u041a\u0440\u0438\u0442\u0435\u0440\u0438\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0413\u0440\u0443\u043f\u043f
+anyObjectMatchingCond=\u041a\u0440\u0438\u0442\u0435\u0440\u0438\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u041e\u0431\u044a\u0435\u043a\u0442\u043e\u0432
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Mapping.html
similarity index 88%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Mapping.html
index 6f94ce5..2729673 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Mapping.html
@@ -17,7 +17,7 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <wicket:extend>
-    <div wicket:id="parametersDetailsPanel">[parametersDetailsPanel]</div>
-  </wicket:extend>
+  <wicket:panel>
+    <span wicket:id="mapping"/>
+  </wicket:panel>
 </html>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html
similarity index 76%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html
index 6f94ce5..beba307 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersEditModalPanel.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html
@@ -17,7 +17,9 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <wicket:extend>
-    <div wicket:id="parametersDetailsPanel">[parametersDetailsPanel]</div>
-  </wicket:extend>
+  <wicket:panel>
+    <div class="form-group"><span wicket:id="key">[key]</span></div>
+    <div class="form-group"><span wicket:id="description">[description]</span></div>
+    <div class="form-group"><span wicket:id="conf">[conf]</span></div>
+  </wicket:panel>
 </html>
diff --git a/wa/starter/src/test/resources/debug/application-debug.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.properties
similarity index 92%
copy from wa/starter/src/test/resources/debug/application-debug.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.properties
index 8a2c08a..18cf102 100644
--- a/wa/starter/src/test/resources/debug/application-debug.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.properties
@@ -14,4 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#debug=true
+description=Description
+configuration=Configuration
+type=Type
diff --git a/wa/starter/src/test/resources/debug/application-debug.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_fr_CA.properties
similarity index 92%
copy from wa/starter/src/test/resources/debug/application-debug.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_fr_CA.properties
index 8a2c08a..18cf102 100644
--- a/wa/starter/src/test/resources/debug/application-debug.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_fr_CA.properties
@@ -14,4 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#debug=true
+description=Description
+configuration=Configuration
+type=Type
diff --git a/wa/starter/src/test/resources/debug/application-debug.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_it.properties
similarity index 92%
copy from wa/starter/src/test/resources/debug/application-debug.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_it.properties
index 8a2c08a..98514ae 100644
--- a/wa/starter/src/test/resources/debug/application-debug.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_it.properties
@@ -14,4 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#debug=true
+description=Descrizione
+configuration=Configurazione
+type=Tipo
diff --git a/wa/starter/src/test/resources/debug/application-debug.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_ja.properties
similarity index 92%
copy from wa/starter/src/test/resources/debug/application-debug.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_ja.properties
index 8a2c08a..82b26f2 100644
--- a/wa/starter/src/test/resources/debug/application-debug.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_ja.properties
@@ -14,4 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#debug=true
+description=Description
+configuration=\u8a2d\u5b9a
+type=Type
diff --git a/wa/starter/src/test/resources/debug/application-debug.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_pt_BR.properties
similarity index 92%
copy from wa/starter/src/test/resources/debug/application-debug.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_pt_BR.properties
index 8a2c08a..18cf102 100644
--- a/wa/starter/src/test/resources/debug/application-debug.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_pt_BR.properties
@@ -14,4 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-#debug=true
+description=Description
+configuration=Configuration
+type=Type
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_ru.properties
similarity index 86%
copy from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
copy to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_ru.properties
index b8dd372..9b16864 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile_ru.properties
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-policy.account=Account
-policy.password=Password
-policy.pull=Pull
-policy.push=Push
+#
+description=Description
+configuration=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f
+type=Type
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/SyncopeIdMConsoleContext.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/SyncopeIdMConsoleContext.java
index 6f9e87a..d2b58b4 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/SyncopeIdMConsoleContext.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/SyncopeIdMConsoleContext.java
@@ -76,7 +76,7 @@ public class SyncopeIdMConsoleContext {
     }
 
     @Bean
-    public PolicyTabProvider policyTabProvider() {
+    public PolicyTabProvider idmPolicyTabProvider() {
         return new IdMPolicyTabProvider();
     }
 }
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
index d3b1630..cc63b83 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.client.console.commons;
 
+import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.client.console.policies.PullPolicyDirectoryPanel;
 import org.apache.syncope.client.console.policies.PushPolicyDirectoryPanel;
@@ -27,13 +28,18 @@ import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.ResourceModel;
 
-public class IdMPolicyTabProvider extends IdRepoPolicyTabProvider {
+public class IdMPolicyTabProvider implements PolicyTabProvider {
 
     private static final long serialVersionUID = 2822554006571803418L;
 
     @Override
+    public int getOrder() {
+        return 300;
+    }
+
+    @Override
     public List<ITab> buildTabList(final PageReference pageRef) {
-        List<ITab> tabs = super.buildTabList(pageRef);
+        List<ITab> tabs = new ArrayList<>();
 
         tabs.add(new AbstractTab(new ResourceModel("policy.pull")) {
 
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/search/ConnObjectSearchPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/search/ConnObjectSearchPanel.java
index b078a40..793b322 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/search/ConnObjectSearchPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/panels/search/ConnObjectSearchPanel.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.panels.search;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -85,7 +84,7 @@ public class ConnObjectSearchPanel extends AbstractSearchPanel {
 
             @Override
             protected List<SearchClause.Type> load() {
-                return Collections.singletonList(SearchClause.Type.ATTRIBUTE);
+                return List.of(SearchClause.Type.ATTRIBUTE);
             }
         };
 
@@ -95,7 +94,7 @@ public class ConnObjectSearchPanel extends AbstractSearchPanel {
 
             @Override
             protected Map<String, PlainSchemaTO> load() {
-                return Collections.emptyMap();
+                return Map.of();
             }
         };
 
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
index 6a97dca..63219d7 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
@@ -43,7 +43,7 @@ public class PullPolicyDirectoryPanel extends PolicyDirectoryPanel<PullPolicyTO>
     public PullPolicyDirectoryPanel(final String id, final PageReference pageRef) {
         super(id, PolicyType.PULL, pageRef);
 
-        final PullPolicyTO defaultItem = new PullPolicyTO();
+        PullPolicyTO defaultItem = new PullPolicyTO();
 
         this.addNewItemPanelBuilder(
                 new PolicyModalPanelBuilder<>(PolicyType.PULL, defaultItem, modal, pageRef), true);
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java
index cb6f9e5..adcd73b 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java
@@ -43,7 +43,7 @@ public class PushPolicyDirectoryPanel extends PolicyDirectoryPanel<PushPolicyTO>
     public PushPolicyDirectoryPanel(final String id, final PageReference pageRef) {
         super(id, PolicyType.PUSH, pageRef);
 
-        final PushPolicyTO defaultItem = new PushPolicyTO();
+        PushPolicyTO defaultItem = new PushPolicyTO();
 
         this.addNewItemPanelBuilder(
                 new PolicyModalPanelBuilder<>(PolicyType.PUSH, defaultItem, modal, pageRef), true);
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
index 6655769..9b882b5 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
@@ -84,7 +84,6 @@ public class ResourceMappingPanel extends AbstractMappingPanel {
                 jexlTransformers,
                 new ListModel<ItemTO>(provision.getItems()),
                 resourceTO.getConnector() != null,
-                false,
                 MappingPurpose.BOTH);
 
         setOutputMarkupId(true);
diff --git a/client/idrepo/common-ui/pom.xml b/client/idrepo/common-ui/pom.xml
index d8be621..583c570 100644
--- a/client/idrepo/common-ui/pom.xml
+++ b/client/idrepo/common-ui/pom.xml
@@ -59,6 +59,10 @@ under the License.
       <artifactId>wicket-auth-roles</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.wicketstuff</groupId>
+      <artifactId>wicketstuff-editable-grid</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.wicket</groupId>
       <artifactId>wicket-native-websocket-javax</artifactId>
     </dependency>
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid.java
new file mode 100644
index 0000000..8bd45be
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.ui.commons.markup.html.form;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.tuple.MutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.IFormSubmitter;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.wicketstuff.egrid.column.EditableGridActionsColumn;
+import org.wicketstuff.egrid.column.EditableGridActionsPanel;
+import org.wicketstuff.egrid.component.EditableDataTable;
+import org.wicketstuff.egrid.model.GridOperationData;
+import org.wicketstuff.egrid.model.OperationType;
+import org.wicketstuff.egrid.provider.IEditableDataProvider;
+import org.wicketstuff.egrid.toolbar.EditableGridHeadersToolbar;
+import org.wicketstuff.egrid.toolbar.EditableGridNavigationToolbar;
+
+public class AjaxGrid<K, V, S> extends Panel {
+
+    private static final long serialVersionUID = 1L;
+
+    protected static class NonValidatingForm<T> extends Form<T> {
+
+        protected static final long serialVersionUID = 1L;
+
+        public NonValidatingForm(final String id) {
+            super(id);
+        }
+
+        @Override
+        public void process(final IFormSubmitter submittingComponent) {
+            delegateSubmit(submittingComponent);
+        }
+    }
+
+    protected EditableDataTable<Pair<K, V>, S> dataTable;
+
+    public AjaxGrid(
+            final String id,
+            final List<? extends IColumn<Pair<K, V>, S>> columns,
+            final IEditableDataProvider<Pair<K, V>, S> dataProvider,
+            final long rowsPerPage) {
+
+        super(id);
+
+        List<IColumn<Pair<K, V>, S>> newCols = new ArrayList<>();
+        newCols.addAll(columns);
+        newCols.add(new AjaxGridActionsColumn<>(new Model<>("Actions")));
+
+        dataTable = new EditableDataTable<Pair<K, V>, S>("dataTable", newCols, dataProvider, rowsPerPage, null) {
+
+            protected static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onError(final AjaxRequestTarget target) {
+                AjaxGrid.this.onError(target);
+            }
+
+            @Override
+            protected Item<Pair<K, V>> newRowItem(final String id, final int index, final IModel<Pair<K, V>> model) {
+                return super.newRowItem(id, index, model);
+            }
+        };
+
+        dataTable.setOutputMarkupId(true);
+
+        dataTable.addTopToolbar(new EditableGridNavigationToolbar(dataTable));
+        if (displayHeader()) {
+            dataTable.addTopToolbar(new EditableGridHeadersToolbar<>(dataTable, dataProvider));
+        }
+        if (displayAdd()) {
+            dataTable.addBottomToolbar(newAddBottomToolbar(dataTable, dataProvider));
+        }
+
+        Form<Pair<K, V>> form = new NonValidatingForm<>("form");
+        form.setOutputMarkupId(true);
+        form.add(dataTable);
+        add(form);
+    }
+
+    public AjaxGrid<K, V, S> setTableBodyCss(final String cssStyle) {
+        dataTable.setTableBodyCss(cssStyle);
+        return this;
+    }
+
+    public AjaxGrid<K, V, S> setTableCss(final String cssStyle) {
+        dataTable.add(AttributeModifier.replace("class", cssStyle));
+        return this;
+    }
+
+    protected EditableDataTable.RowItem<Pair<K, V>> newRowItem(
+            final String id, final int index, final IModel<Pair<K, V>> model) {
+
+        return new EditableDataTable.RowItem<>(id, index, model);
+    }
+
+    protected AjaxGridBottomToolbar<Pair<K, V>, S> newAddBottomToolbar(
+            final EditableDataTable<Pair<K, V>, S> dataTable,
+            final IEditableDataProvider<Pair<K, V>, S> dataProvider) {
+
+        return new AjaxGridBottomToolbar<Pair<K, V>, S>(dataTable) {
+
+            protected static final long serialVersionUID = 1L;
+
+            @Override
+            protected Pair<K, V> newRowInstance() {
+                return new MutablePair<>();
+            }
+
+            @Override
+            protected void onAdd(final AjaxRequestTarget target, final Pair<K, V> newRow) {
+                dataProvider.add(newRow);
+                target.add(dataTable);
+                AjaxGrid.this.onAdd(target, newRow);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target) {
+                super.onError(target);
+                AjaxGrid.this.onError(target);
+            }
+        };
+    }
+
+    protected boolean allowDelete(final Item<Pair<K, V>> rowItem) {
+        return true;
+    }
+
+    protected boolean displayHeader() {
+        return true;
+    }
+
+    protected boolean displayAdd() {
+        return true;
+    }
+
+    protected void onCancel(final AjaxRequestTarget target) {
+    }
+
+    protected void onDelete(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+    }
+
+    protected void onSave(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+    }
+
+    protected void onError(final AjaxRequestTarget target) {
+    }
+
+    protected void onAdd(final AjaxRequestTarget target, final Pair<K, V> newRow) {
+    }
+
+    protected class AjaxGridActionsColumn<P, S> extends EditableGridActionsColumn<Pair<K, V>, S> {
+
+        protected static final long serialVersionUID = 1L;
+
+        public AjaxGridActionsColumn(final IModel<String> displayModel) {
+            super(displayModel);
+        }
+
+        @Override
+        public void populateItem(
+                final Item<ICellPopulator<Pair<K, V>>> item,
+                final String componentId,
+                final IModel<Pair<K, V>> rowModel) {
+
+            item.add(new AjaxGridActionsPanel<>(componentId, item));
+        }
+
+        @Override
+        protected void onError(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+            AjaxGrid.this.onError(target);
+        }
+
+        @Override
+        protected void onSave(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+            AjaxGrid.this.onSave(target, rowModel);
+        }
+
+        @Override
+        protected void onDelete(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+            AjaxGrid.this.onDelete(target, rowModel);
+        }
+
+        @Override
+        protected void onCancel(final AjaxRequestTarget target) {
+            AjaxGrid.this.onCancel(target);
+        }
+
+        @Override
+        protected boolean allowDelete(final Item<Pair<K, V>> rowItem) {
+            return AjaxGrid.this.allowDelete(rowItem);
+        }
+    }
+
+    protected class AjaxGridActionsPanel<T> extends EditableGridActionsPanel<Pair<K, V>> {
+
+        private final Item<Pair<K, V>> rowItem;
+
+        @SuppressWarnings("unchecked")
+        public AjaxGridActionsPanel(final String id, final Item<ICellPopulator<Pair<K, V>>> item) {
+            super(id, item);
+
+            rowItem = item.findParent(Item.class);
+            addOrReplace(new AjaxLink<String>("delete") {
+
+                @SuppressWarnings("unchecked")
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    EditableDataTable eventTarget = rowItem.findParent(EditableDataTable.class);
+                    send(getPage(), Broadcast.BREADTH, new GridOperationData<>(
+                            OperationType.DELETE, (T) rowItem.getDefaultModelObject(), eventTarget));
+                    target.add(eventTarget);
+                    onDelete(target);
+                }
+
+                @Override
+                public boolean isVisible() {
+                    return AjaxGridActionsPanel.this.allowDelete(rowItem);
+                }
+            });
+        }
+
+        @Override
+        protected void onSave(final AjaxRequestTarget target) {
+            AjaxGrid.this.onSave(target, rowItem.getModel());
+        }
+
+        @Override
+        protected void onError(final AjaxRequestTarget target) {
+            AjaxGrid.this.onError(target);
+        }
+
+        @Override
+        protected void onCancel(final AjaxRequestTarget target) {
+            AjaxGrid.this.onCancel(target);
+        }
+
+        @Override
+        protected void onDelete(final AjaxRequestTarget target) {
+            AjaxGrid.this.onDelete(target, rowItem.getModel());
+        }
+    }
+}
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridBottomToolbar.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridBottomToolbar.java
new file mode 100644
index 0000000..1e701fa
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridBottomToolbar.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.ui.commons.markup.html.form;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.IFormVisitorParticipant;
+import org.apache.wicket.markup.html.list.Loop;
+import org.apache.wicket.markup.html.list.LoopItem;
+import org.apache.wicket.model.PropertyModel;
+import org.wicketstuff.egrid.column.AbstractEditablePropertyColumn;
+import org.wicketstuff.egrid.column.EditableCellPanel;
+import org.wicketstuff.egrid.component.EditableDataTable;
+import org.wicketstuff.egrid.component.EditableGridSubmitLink;
+import org.wicketstuff.egrid.toolbar.AbstractEditableGridToolbar;
+
+public abstract class AjaxGridBottomToolbar<T, S> extends AbstractEditableGridToolbar {
+
+    private static final long serialVersionUID = 1L;
+
+    protected static final String CELL_ID = "cell";
+
+    protected static final String CELLS_ID = "cells";
+
+    protected T newRow = null;
+
+    public AjaxGridBottomToolbar(final EditableDataTable<?, ?> table) {
+        super(table);
+
+        newRow = newRowInstance();
+
+        MarkupContainer td = new WebMarkupContainer("td");
+        td.add(new AttributeModifier("colspan", table.getColumns().size() - 1));
+        AddToolBarForm addToolBarForm = new AddToolBarForm("addToolbarForm");
+        td.add(addToolBarForm);
+        add(td);
+        add(newAddButton(addToolBarForm));
+    }
+
+    protected abstract T newRowInstance();
+
+    protected abstract void onAdd(AjaxRequestTarget target, T newRow);
+
+    protected void onError(final AjaxRequestTarget target) {
+    }
+
+    protected class AddToolBarForm extends Form<T> implements IFormVisitorParticipant {
+
+        protected static final long serialVersionUID = 1L;
+
+        public AddToolBarForm(final String id) {
+            super(id);
+            add(newEditorComponents());
+        }
+
+        @Override
+        public boolean processChildren() {
+            return Optional.ofNullable(getRootForm().findSubmitter()).
+                    map(submitter -> submitter.getForm() == this).
+                    orElse(false);
+        }
+    }
+
+    protected Component newAddButton(final WebMarkupContainer encapsulatingContainer) {
+        return new EditableGridSubmitLink("add", encapsulatingContainer) {
+
+            protected static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onSuccess(final AjaxRequestTarget target) {
+                onAdd(target, newRow);
+                newRow = newRowInstance();
+                target.add(getTable());
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target) {
+                AjaxGridBottomToolbar.this.onError(target);
+            }
+        };
+    }
+
+    protected Loop newEditorComponents() {
+        List<AbstractEditablePropertyColumn<T, S>> columns = getEditableColumns();
+        return new Loop(CELLS_ID, columns.size()) {
+
+            protected static final long serialVersionUID = 1L;
+
+            @Override
+            protected void populateItem(final LoopItem item) {
+                addEditorComponent(item, getEditorColumn(columns, item.getIndex()));
+            }
+        };
+    }
+
+    protected void addEditorComponent(final LoopItem item, final AbstractEditablePropertyColumn<T, S> toolBarCell) {
+        item.add(newCell(toolBarCell));
+    }
+
+    @SuppressWarnings("unchecked")
+    protected List<AbstractEditablePropertyColumn<T, S>> getEditableColumns() {
+        List<AbstractEditablePropertyColumn<T, S>> columns = new ArrayList<>();
+        getTable().getColumns().stream().
+                filter(AbstractEditablePropertyColumn.class::isInstance).
+                map(AbstractEditablePropertyColumn.class::cast).
+                forEach(columns::add);
+        return columns;
+    }
+
+    protected Component newCell(final AbstractEditablePropertyColumn<T, S> editableGridColumn) {
+        EditableCellPanel panel = editableGridColumn.getEditableCellPanel(CELL_ID);
+        FormComponent<?> editorComponent = panel.getEditableComponent();
+        editorComponent.setDefaultModel(new PropertyModel<T>(newRow, editableGridColumn.getPropertyExpression()));
+        return panel;
+    }
+
+    protected AbstractEditablePropertyColumn<T, S> getEditorColumn(
+            final List<AbstractEditablePropertyColumn<T, S>> editorColumn, final int index) {
+
+        return editorColumn.get(index);
+    }
+}
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridFieldPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridFieldPanel.java
new file mode 100644
index 0000000..9b12d10
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridFieldPanel.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.ui.commons.markup.html.form;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.MutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.wicketstuff.egrid.column.AbstractEditablePropertyColumn;
+import org.wicketstuff.egrid.column.RequiredEditableTextFieldColumn;
+import org.wicketstuff.egrid.provider.EditableListDataProvider;
+
+public class AjaxGridFieldPanel<K, V, S> extends Panel {
+
+    public AjaxGridFieldPanel(final String id, final String name, final IModel<Map<K, V>> model) {
+        super(id, model);
+
+        add(new Label(AbstractFieldPanel.LABEL, new ResourceModel(name, name)));
+
+        add(new AjaxGrid<K, V, S>(
+                "grid",
+                getColumns(),
+                new EditableListDataProvider<Pair<K, V>, S>(model.getObject().entrySet().stream().
+                        map(entry -> MutablePair.of(entry.getKey(), entry.getValue())).
+                        collect(Collectors.toList())), 10) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected boolean displayHeader() {
+                return false;
+            }
+
+            @Override
+            protected void onAdd(final AjaxRequestTarget target, final Pair<K, V> newRow) {
+                model.getObject().put(newRow.getLeft(), newRow.getRight());
+            }
+
+            @Override
+            protected void onDelete(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+                model.getObject().remove(rowModel.getObject().getLeft());
+            }
+
+            @Override
+            protected void onSave(final AjaxRequestTarget target, final IModel<Pair<K, V>> rowModel) {
+                model.getObject().put(rowModel.getObject().getLeft(), rowModel.getObject().getRight());
+            }
+        });
+    }
+
+    public AjaxGridFieldPanel hideLabel() {
+        Component label = get(AbstractFieldPanel.LABEL);
+        if (label != null) {
+            label.setVisible(false);
+        }
+
+        return this;
+    }
+
+    private List<AbstractEditablePropertyColumn<Pair<K, V>, S>> getColumns() {
+        List<AbstractEditablePropertyColumn<Pair<K, V>, S>> columns = new ArrayList<>();
+        columns.add(new RequiredEditableTextFieldColumn<>(Model.of(), "left"));
+        columns.add(new RequiredEditableTextFieldColumn<>(Model.of(), "right"));
+        return columns;
+    }
+}
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/FieldPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/FieldPanel.java
index f587c29..5983720 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/FieldPanel.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/FieldPanel.java
@@ -24,7 +24,6 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig
 import java.io.Serializable;
 import java.util.List;
 import java.util.Optional;
-
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.Attributable;
@@ -71,7 +70,7 @@ public abstract class FieldPanel<T extends Serializable> extends AbstractFieldPa
         this.title = title;
         field.add(new PopoverBehavior(
                 Model.<String>of(),
-            Optional.ofNullable(title).map(Model::of).orElseGet(Model::<String>of),
+                Optional.ofNullable(title).map(Model::of).orElseGet(Model::<String>of),
                 new PopoverConfig().withHtml(html).withHoverTrigger().withPlacement(
                         index.getObject() != null && index.getObject() == 0
                         ? TooltipConfig.Placement.bottom
diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxCheckBoxPanel.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxCheckBoxPanel.html
index e2efccd..9f02c7b 100644
--- a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxCheckBoxPanel.html
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxCheckBoxPanel.html
@@ -17,20 +17,15 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <head>
-    <title>Ajax checkbox panel</title>
-  </head>
-  <body>
-    <wicket:extend>
-      <div class="checkbox">
-        <label style="width:100%">
-          <input type="checkbox" wicket:id="checkboxField" />
-          <wicket:enclosure child="field-label">
-            <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>
-            <span wicket:id="externalAction"/>
-          </wicket:enclosure>
-        </label>
-      </div>
-    </wicket:extend>
-  </body>
+  <wicket:extend>
+    <div class="checkbox">
+      <label style="width:100%">
+        <input type="checkbox" wicket:id="checkboxField" />
+        <wicket:enclosure child="field-label">
+          <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>
+          <span wicket:id="externalAction"/>
+        </wicket:enclosure>
+      </label>
+    </div>
+  </wicket:extend>
 </html>
diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid$AjaxGridActionsPanel.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid$AjaxGridActionsPanel.html
new file mode 100644
index 0000000..b8f41a2
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid$AjaxGridActionsPanel.html
@@ -0,0 +1,24 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:panel>
+    <a wicket:id="edit" href="#"><i class="far fa-edit"></i></a>
+    <a wicket:id="save" href="#"><i class="far fa-save"></i></a>
+    <a wicket:id="cancel" href="#"><i class="far fa-window-close"></i></a>
+    <a wicket:id="delete" href="#"><i class="far fa-minus-square"></i></a>
+  </wicket:panel>
+</html>
diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid.html
new file mode 100644
index 0000000..2225cea
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGrid.html
@@ -0,0 +1,23 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:panel>
+    <form wicket:id="form">
+      <table wicket:id="dataTable"></table>
+    </form>
+  </wicket:panel>
+</html>
diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridBottomToolbar.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridBottomToolbar.html
new file mode 100644
index 0000000..c8f37e3
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridBottomToolbar.html
@@ -0,0 +1,32 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:panel>
+    <tr>
+      <td wicket:id="td" colspan="3">
+        <form wicket:id ="addToolbarForm">
+          <span wicket:id="cells">
+            <span wicket:id="cell">[cell data]</span>
+          </span>								
+        </form>	
+      </td>
+      <td>							
+        <a wicket:id="add" href="#"><i class="far fa-plus-square"></i></a> 
+      </td>
+    </tr>
+  </wicket:panel>
+</html>
diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridFieldPanel.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridFieldPanel.html
new file mode 100644
index 0000000..5df1f02
--- /dev/null
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxGridFieldPanel.html
@@ -0,0 +1,24 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:panel>
+    <wicket:enclosure child="field-label">
+      <label wicket:id="field-label">[LABEL]</label>
+    </wicket:enclosure>
+    <div wicket:id="grid"></div>
+  </wicket:panel>
+</html>
diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPasswordFieldPanel.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPasswordFieldPanel.html
index f83c16a..30329ae 100644
--- a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPasswordFieldPanel.html
+++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxPasswordFieldPanel.html
@@ -17,16 +17,11 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <head>
-    <title>Ajaxt password field panel</title>
-  </head>
-  <body>
-    <wicket:extend>
-      <wicket:enclosure child="field-label">
-        <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>
-        <span wicket:id="externalAction"/>
-      </wicket:enclosure>
-      <input type="password" class="form-control" wicket:id="passwordField" />
-    </wicket:extend>
-  </body>
+  <wicket:extend>
+    <wicket:enclosure child="field-label">
+      <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>
+      <span wicket:id="externalAction"/>
+    </wicket:enclosure>
+    <input type="password" class="form-control" wicket:id="passwordField" />
+  </wicket:extend>
 </html>
\ No newline at end of file
diff --git a/client/idrepo/console/pom.xml b/client/idrepo/console/pom.xml
index 9b2982e..456973c 100644
--- a/client/idrepo/console/pom.xml
+++ b/client/idrepo/console/pom.xml
@@ -260,6 +260,7 @@ under the License.
             <configuration>
               <jvmArguments>
                 -Dwicket.core.settings.general.configuration-type=development
+                -XX:HotswapAgent=fatjar
                 -Xdebug -Xrunjdwp:transport=dt_socket,address=8003,server=y,suspend=n
               </jvmArguments>
               <profiles>
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
index 03a74a2..469116c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
@@ -29,11 +29,13 @@ import org.apache.syncope.client.console.commons.IdRepoAnyWizardBuilderAdditiona
 import org.apache.syncope.client.console.commons.IdRepoExternalResourceProvider;
 import org.apache.syncope.client.console.commons.IdRepoImplementationInfoProvider;
 import org.apache.syncope.client.console.commons.IdRepoPolicyTabProvider;
+import org.apache.syncope.client.console.commons.IdRepoRealmPolicyProvider;
 import org.apache.syncope.client.console.commons.IdRepoStatusProvider;
 import org.apache.syncope.client.console.commons.IdRepoVirSchemaDetailsPanelProvider;
 import org.apache.syncope.client.console.commons.ImplementationInfoProvider;
 import org.apache.syncope.client.console.commons.PolicyTabProvider;
 import org.apache.syncope.client.console.commons.PreviewUtils;
+import org.apache.syncope.client.console.commons.RealmPolicyProvider;
 import org.apache.syncope.client.console.commons.StatusProvider;
 import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
@@ -152,9 +154,14 @@ public class SyncopeConsoleApplication extends SpringBootServletInitializer {
         return new IdRepoImplementationInfoProvider();
     }
 
-    @ConditionalOnMissingBean(name = "policyTabProvider")
+    @ConditionalOnMissingBean(name = "realmPolicyProvider")
     @Bean
-    public PolicyTabProvider policyTabProvider() {
+    public RealmPolicyProvider realmPolicyProvider() {
+        return new IdRepoRealmPolicyProvider();
+    }
+
+    @Bean
+    public PolicyTabProvider idRepoPolicyTabProvider() {
         return new IdRepoPolicyTabProvider();
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
index e5b7258..7e1ca1b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
@@ -24,6 +24,7 @@ import de.agilecoders.wicket.core.Bootstrap;
 import de.agilecoders.wicket.core.settings.BootstrapSettings;
 import de.agilecoders.wicket.core.settings.IBootstrapSettings;
 import de.agilecoders.wicket.core.settings.SingleThemeProvider;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -77,6 +78,7 @@ import org.apache.wicket.request.component.IRequestablePage;
 import org.apache.wicket.request.cycle.IRequestCycleListener;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -140,7 +142,7 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
     private ImplementationInfoProvider implementationInfoProvider;
 
     @Autowired
-    private PolicyTabProvider policyTabProvider;
+    private ApplicationContext ctx;
 
     private Map<String, Class<? extends BasePage>> pageClasses;
 
@@ -249,7 +251,7 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
 
         getSecuritySettings().setAuthorizationStrategy(new MetaDataRoleAuthorizationStrategy(this));
 
-        lookup.getPageClasses().
+        lookup.getIdRepoPageClasses().
                 forEach(cls -> MetaDataRoleAuthorizationStrategy.authorize(cls, Constants.ROLE_AUTHENTICATED));
 
         getMarkupSettings().setStripWicketTags(true);
@@ -319,7 +321,7 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
         }
         Args.notNull(reconciliationReportKey, "<reconciliationReportKey>");
 
-        for (Class<? extends AbstractResource> resource : lookup.getResources()) {
+        for (Class<? extends AbstractResource> resource : lookup.getClasses(AbstractResource.class)) {
             Resource annotation = resource.getAnnotation(Resource.class);
             try {
                 AbstractResource instance = resource.getDeclaredConstructor().newInstance();
@@ -436,7 +438,7 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
         return implementationInfoProvider;
     }
 
-    public PolicyTabProvider getPolicyTabProvider() {
-        return policyTabProvider;
+    public Collection<PolicyTabProvider> getPolicyTabProviders() {
+        return ctx.getBeansOfType(PolicyTabProvider.class).values();
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java
index e22d101..ebfdf65 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java
@@ -33,6 +33,11 @@ public class IdRepoPolicyTabProvider implements PolicyTabProvider {
     private static final long serialVersionUID = 5017230231088263303L;
 
     @Override
+    public int getOrder() {
+        return 100;
+    }
+
+    @Override
     public List<ITab> buildTabList(final PageReference pageRef) {
         List<ITab> tabs = new ArrayList<>();
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoRealmPolicyProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoRealmPolicyProvider.java
new file mode 100644
index 0000000..7a9abbb
--- /dev/null
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoRealmPolicyProvider.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.rest.PolicyRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.policy.PolicyTO;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.repeater.RepeatingView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class IdRepoRealmPolicyProvider implements RealmPolicyProvider {
+
+    private static final long serialVersionUID = 1L;
+
+    private final IModel<Map<String, String>> accountPolicies = new LoadableDetachableModel<Map<String, String>>() {
+
+        private static final long serialVersionUID = -2012833443695917883L;
+
+        @Override
+        protected Map<String, String> load() {
+            return PolicyRestClient.getPolicies(PolicyType.ACCOUNT).stream().
+                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
+        }
+    };
+
+    private final IModel<Map<String, String>> passwordPolicies = new LoadableDetachableModel<Map<String, String>>() {
+
+        private static final long serialVersionUID = -2012833443695917883L;
+
+        @Override
+        protected Map<String, String> load() {
+            return PolicyRestClient.getPolicies(PolicyType.PASSWORD).stream().
+                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
+        }
+    };
+
+    @Override
+    public void add(final RealmTO realmTO, final RepeatingView view) {
+        AjaxDropDownChoicePanel<String> accountPolicy = new AjaxDropDownChoicePanel<>(
+                view.newChildId(),
+                new ResourceModel("accountPolicy", "accountPolicy").getObject(),
+                new PropertyModel<>(realmTO, "accountPolicy"),
+                false);
+        accountPolicy.setChoiceRenderer(new PolicyRenderer(accountPolicies));
+        accountPolicy.setChoices(new ArrayList<>(accountPolicies.getObject().keySet()));
+        ((DropDownChoice<?>) accountPolicy.getField()).setNullValid(true);
+        view.add(accountPolicy);
+
+        AjaxDropDownChoicePanel<String> passwordPolicy = new AjaxDropDownChoicePanel<>(
+                view.newChildId(),
+                new ResourceModel("passwordPolicy", "passwordPolicy").getObject(),
+                new PropertyModel<>(realmTO, "passwordPolicy"),
+                false);
+        passwordPolicy.setChoiceRenderer(new PolicyRenderer(passwordPolicies));
+        passwordPolicy.setChoices(new ArrayList<>(passwordPolicies.getObject().keySet()));
+        ((DropDownChoice<?>) passwordPolicy.getField()).setNullValid(true);
+        view.add(passwordPolicy);
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
index 05882c5..56a2dc7 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
@@ -22,9 +22,9 @@ import java.io.Serializable;
 import java.util.List;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.springframework.core.Ordered;
 
-@FunctionalInterface
-public interface PolicyTabProvider extends Serializable {
+public interface PolicyTabProvider extends Serializable, Ordered {
 
     List<ITab> buildTabList(PageReference pageRef);
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AbstractAuthModuleConf.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmPolicyProvider.java
similarity index 73%
rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AbstractAuthModuleConf.java
rename to client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmPolicyProvider.java
index 9a28b37..0a7eeb0 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AbstractAuthModuleConf.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/RealmPolicyProvider.java
@@ -16,12 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.auth;
+package org.apache.syncope.client.console.commons;
 
-import org.apache.syncope.common.lib.BaseBean;
+import java.io.Serializable;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.wicket.markup.repeater.RepeatingView;
 
-public abstract class AbstractAuthModuleConf implements BaseBean, AuthModuleConf {
-
-    private static final long serialVersionUID = 4153200197344709778L;
+public interface RealmPolicyProvider extends Serializable {
 
+    void add(RealmTO realmTO, RepeatingView view);
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
index 2eebb4c..cc2c2e1 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.syncope.client.console.annotations.AMPage;
 import org.apache.syncope.client.ui.commons.annotations.ExtPage;
@@ -38,7 +39,6 @@ import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
 import org.apache.syncope.client.ui.commons.annotations.ExtWidget;
 import org.apache.syncope.client.console.annotations.IdMPage;
 import org.apache.syncope.client.ui.commons.annotations.Resource;
-import org.apache.syncope.client.console.commons.AnyWizardBuilderAdditionalSteps;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.ui.commons.panels.BaseSSOLoginFormPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.preview.AbstractBinaryPreviewer;
@@ -58,19 +58,13 @@ import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
 import org.springframework.core.type.filter.AssignableTypeFilter;
 import org.springframework.util.ClassUtils;
-import org.apache.syncope.client.console.commons.ExternalResourceProvider;
-import org.apache.syncope.client.console.commons.ImplementationInfoProvider;
-import org.apache.syncope.client.console.commons.PolicyTabProvider;
-import org.apache.syncope.client.console.commons.StatusProvider;
-import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
-import org.apache.syncope.client.console.commons.AnyDirectoryPanelAdditionalActionLinksProvider;
 import org.apache.syncope.client.console.wizards.any.UserFormFinalizer;
 import org.apache.syncope.client.console.annotations.UserFormFinalize;
 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 
 public class ClassPathScanImplementationLookup {
 
-    private static final Logger LOG = LoggerFactory.getLogger(ClassPathScanImplementationLookup.class);
+    protected static final Logger LOG = LoggerFactory.getLogger(ClassPathScanImplementationLookup.class);
 
     private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope";
 
@@ -101,24 +95,14 @@ public class ClassPathScanImplementationLookup {
         });
     }
 
-    private List<Class<? extends BasePage>> pages;
+    private Map<String, List<Class<?>>> classes;
 
-    private List<Class<? extends AbstractBinaryPreviewer>> previewers;
-
-    private List<Class<? extends UserFormFinalizer>> userFormFinalizers;
+    private List<Class<? extends BasePage>> idRepoPages;
 
     private List<Class<? extends BasePage>> idmPages;
 
     private List<Class<? extends BasePage>> amPages;
 
-    private List<Class<? extends BaseExtPage>> extPages;
-
-    private List<Class<? extends BaseExtWidget>> extWidgets;
-
-    private List<Class<? extends ExtAlertWidget<?>>> extAlertWidgets;
-
-    private List<Class<? extends BaseSSOLoginFormPanel>> ssoLoginFormPanels;
-
     private Map<String, Class<? extends ReportletConf>> reportletConfs;
 
     private Map<String, Class<? extends AccountRuleConf>> accountRuleConfs;
@@ -129,8 +113,6 @@ public class ClassPathScanImplementationLookup {
 
     private Map<String, Class<? extends PushCorrelationRuleConf>> pushCorrelationRuleConfs;
 
-    private List<Class<? extends AbstractResource>> resources;
-
     /**
      * This method can be overridden by subclasses to customize classpath scan.
      *
@@ -140,25 +122,9 @@ public class ClassPathScanImplementationLookup {
         return DEFAULT_BASE_PACKAGE;
     }
 
-    @SuppressWarnings("unchecked")
-    public void load() {
-        pages = new ArrayList<>();
-        previewers = new ArrayList<>();
-        userFormFinalizers = new ArrayList<>();
-        idmPages = new ArrayList<>();
-        amPages = new ArrayList<>();
-        extPages = new ArrayList<>();
-        extWidgets = new ArrayList<>();
-        extAlertWidgets = new ArrayList<>();
-        ssoLoginFormPanels = new ArrayList<>();
-        reportletConfs = new HashMap<>();
-        accountRuleConfs = new HashMap<>();
-        passwordRuleConfs = new HashMap<>();
-        pullCorrelationRuleConfs = new HashMap<>();
-        pushCorrelationRuleConfs = new HashMap<>();
-        resources = new ArrayList<>();
-
+    protected ClassPathScanningCandidateComponentProvider scanner() {
         ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
+
         scanner.addIncludeFilter(new AssignableTypeFilter(BasePage.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(AbstractBinaryPreviewer.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(UserFormFinalizer.class));
@@ -172,39 +138,60 @@ public class ClassPathScanImplementationLookup {
         scanner.addIncludeFilter(new AssignableTypeFilter(PullCorrelationRuleConf.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PushCorrelationRuleConf.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(AbstractResource.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(ExternalResourceProvider.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(AnyWizardBuilderAdditionalSteps.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(StatusProvider.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(VirSchemaDetailsPanelProvider.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(AnyDirectoryPanelAdditionalActionLinksProvider.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(ImplementationInfoProvider.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(PolicyTabProvider.class));
-
-        scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
+
+        return scanner;
+    }
+
+    protected void addClass(final String category, final Class<?> clazz) {
+        List<Class<?>> clazzes = classes.get(category);
+        if (clazzes == null) {
+            clazzes = new ArrayList<>();
+            classes.put(category, clazzes);
+        }
+        clazzes.add(clazz);
+    }
+
+    protected void additional(final Class<?> clazz) {
+        // nothing to do
+    }
+
+    @SuppressWarnings("unchecked")
+    public void load() {
+        classes = new HashMap<>();
+        idRepoPages = new ArrayList<>();
+        idmPages = new ArrayList<>();
+        amPages = new ArrayList<>();
+        reportletConfs = new HashMap<>();
+        accountRuleConfs = new HashMap<>();
+        passwordRuleConfs = new HashMap<>();
+        pullCorrelationRuleConfs = new HashMap<>();
+        pushCorrelationRuleConfs = new HashMap<>();
+
+        scanner().findCandidateComponents(getBasePackage()).forEach(bd -> {
             try {
                 Class<?> clazz = ClassUtils.resolveClassName(
                         Objects.requireNonNull(bd.getBeanClassName()), ClassUtils.getDefaultClassLoader());
                 if (!Modifier.isAbstract(clazz.getModifiers())) {
                     if (BaseExtPage.class.isAssignableFrom(clazz)) {
                         if (clazz.isAnnotationPresent(ExtPage.class)) {
-                            extPages.add((Class<? extends BaseExtPage>) clazz);
+                            addClass(BaseExtPage.class.getName(), clazz);
                         } else {
                             LOG.error("Could not find annotation {} in {}, ignoring",
                                     ExtPage.class.getName(), clazz.getName());
                         }
                     } else if (BaseExtWidget.class.isAssignableFrom(clazz)) {
                         if (clazz.isAnnotationPresent(ExtWidget.class)) {
-                            extWidgets.add((Class<? extends BaseExtWidget>) clazz);
+                            addClass(BaseExtWidget.class.getName(), clazz);
                         } else {
                             LOG.error("Could not find annotation {} in {}, ignoring",
                                     ExtWidget.class.getName(), clazz.getName());
                         }
                     } else if (ExtAlertWidget.class.isAssignableFrom(clazz)) {
                         if (clazz.isAnnotationPresent(ExtWidget.class)) {
-                            extAlertWidgets.add((Class<? extends ExtAlertWidget<?>>) clazz);
+                            addClass(ExtAlertWidget.class.getName(), clazz);
                         } else {
                             LOG.error("Could not find annotation {} in {}, ignoring",
-                                    ExtWidget.class.getName(), clazz.getName());
+                                    ExtAlertWidget.class.getName(), clazz.getName());
                         }
                     } else if (BasePage.class.isAssignableFrom(clazz)) {
                         if (clazz.isAnnotationPresent(IdMPage.class)) {
@@ -212,14 +199,14 @@ public class ClassPathScanImplementationLookup {
                         } else if (clazz.isAnnotationPresent(AMPage.class)) {
                             amPages.add((Class<? extends BasePage>) clazz);
                         } else {
-                            pages.add((Class<? extends BasePage>) clazz);
+                            idRepoPages.add((Class<? extends BasePage>) clazz);
                         }
                     } else if (AbstractBinaryPreviewer.class.isAssignableFrom(clazz)) {
-                        previewers.add((Class<? extends AbstractBinaryPreviewer>) clazz);
+                        addClass(AbstractBinaryPreviewer.class.getName(), clazz);
                     } else if (UserFormFinalizer.class.isAssignableFrom(clazz)) {
-                        userFormFinalizers.add((Class<? extends UserFormFinalizer>) clazz);
+                        addClass(UserFormFinalizer.class.getName(), clazz);
                     } else if (BaseSSOLoginFormPanel.class.isAssignableFrom(clazz)) {
-                        ssoLoginFormPanels.add((Class<? extends BaseSSOLoginFormPanel>) clazz);
+                        addClass(BaseSSOLoginFormPanel.class.getName(), clazz);
                     } else if (ReportletConf.class.isAssignableFrom(clazz)) {
                         reportletConfs.put(clazz.getName(), (Class<? extends ReportletConf>) clazz);
                     } else if (AccountRuleConf.class.isAssignableFrom(clazz)) {
@@ -232,21 +219,21 @@ public class ClassPathScanImplementationLookup {
                         pushCorrelationRuleConfs.put(clazz.getName(), (Class<? extends PushCorrelationRuleConf>) clazz);
                     } else if (AbstractResource.class.isAssignableFrom(clazz)) {
                         if (clazz.isAnnotationPresent(Resource.class)) {
-                            resources.add((Class<? extends AbstractResource>) clazz);
+                            addClass(AbstractResource.class.getName(), clazz);
                         } else {
                             LOG.error("Could not find annotation {} in {}, ignoring",
                                     Resource.class.getName(), clazz.getName());
                         }
+                    } else {
+                        additional(clazz);
                     }
                 }
             } catch (Throwable t) {
                 LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
             }
         });
-        pages = Collections.unmodifiableList(pages);
 
-        previewers = Collections.unmodifiableList(previewers);
-        userFormFinalizers = Collections.unmodifiableList(userFormFinalizers);
+        idRepoPages = Collections.unmodifiableList(idRepoPages);
 
         idmPages.sort(Comparator.comparing(o -> o.getAnnotation(IdMPage.class).priority()));
         idmPages = Collections.unmodifiableList(idmPages);
@@ -254,16 +241,22 @@ public class ClassPathScanImplementationLookup {
         amPages.sort(Comparator.comparing(o -> o.getAnnotation(AMPage.class).priority()));
         amPages = Collections.unmodifiableList(amPages);
 
-        extPages.sort(Comparator.comparing(o -> o.getAnnotation(ExtPage.class).priority()));
-        extPages = Collections.unmodifiableList(extPages);
+        if (classes.containsKey(BaseExtPage.class.getName())) {
+            classes.get(BaseExtPage.class.getName()).
+                    sort(Comparator.comparing(o -> o.getAnnotation(ExtPage.class).priority()));
+        }
 
-        extWidgets.sort(Comparator.comparing(o -> o.getAnnotation(ExtWidget.class).priority()));
-        extWidgets = Collections.unmodifiableList(extWidgets);
+        if (classes.containsKey(BaseExtWidget.class.getName())) {
+            classes.get(BaseExtWidget.class.getName()).
+                    sort(Comparator.comparing(o -> o.getAnnotation(ExtWidget.class).priority()));
+        }
 
-        extAlertWidgets.sort(Comparator.comparing(o -> o.getAnnotation(ExtWidget.class).priority()));
-        extAlertWidgets = Collections.unmodifiableList(extAlertWidgets);
+        if (classes.containsKey(ExtAlertWidget.class.getName())) {
+            classes.get(ExtAlertWidget.class.getName()).
+                    sort(Comparator.comparing(o -> o.getAnnotation(ExtWidget.class).priority()));
+        }
 
-        ssoLoginFormPanels = Collections.unmodifiableList(ssoLoginFormPanels);
+        classes.forEach((category, clazzes) -> LOG.debug("{} found: {}", category, clazzes));
 
         reportletConfs = Collections.unmodifiableMap(reportletConfs);
         accountRuleConfs = Collections.unmodifiableMap(accountRuleConfs);
@@ -271,52 +264,15 @@ public class ClassPathScanImplementationLookup {
         pullCorrelationRuleConfs = Collections.unmodifiableMap(pullCorrelationRuleConfs);
         pushCorrelationRuleConfs = Collections.unmodifiableMap(pushCorrelationRuleConfs);
 
-        resources = Collections.unmodifiableList(resources);
-
-        LOG.debug("Binary previewers found: {}", previewers);
-        LOG.debug("User Form finalizers found {}", userFormFinalizers);
-        LOG.debug("Extension pages found: {}", extPages);
-        LOG.debug("Extension widgets found: {}", extWidgets);
-        LOG.debug("Extension alert widgets found: {}", extAlertWidgets);
-        LOG.debug("SSO Login pages found: {}", ssoLoginFormPanels);
         LOG.debug("Reportlet configurations found: {}", reportletConfs);
         LOG.debug("Account Rule configurations found: {}", accountRuleConfs);
         LOG.debug("Password Rule configurations found: {}", passwordRuleConfs);
         LOG.debug("Pull Correlation Rule configurations found: {}", pullCorrelationRuleConfs);
         LOG.debug("Push Correlation Rule configurations found: {}", pushCorrelationRuleConfs);
-        LOG.debug("Wicket Resources found: {}", resources);
     }
 
-    public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final String mimeType) {
-        LOG.debug("Searching for previewer class for MIME type: {}", mimeType);
-        Class<? extends AbstractBinaryPreviewer> previewer = null;
-        for (Class<? extends AbstractBinaryPreviewer> candidate : previewers) {
-            LOG.debug("Evaluating previewer class {} for MIME type {}", candidate.getName(), mimeType);
-            if (candidate.isAnnotationPresent(BinaryPreview.class)
-                    && ArrayUtils.contains(candidate.getAnnotation(BinaryPreview.class).mimeTypes(), mimeType)) {
-                LOG.debug("Found existing previewer for MIME type {}: {}", mimeType, candidate.getName());
-                previewer = candidate;
-            }
-        }
-        return previewer;
-    }
-
-    public List<Class<? extends UserFormFinalizer>> getUserFormFinalizerClasses(final AjaxWizard.Mode mode) {
-        List<Class<? extends UserFormFinalizer>> classes = new ArrayList<>();
-
-        userFormFinalizers.forEach(candidate -> {
-            if (candidate.isAnnotationPresent(UserFormFinalize.class)
-                    && candidate.getAnnotation(UserFormFinalize.class).mode() == mode) {
-
-                classes.add(candidate);
-            }
-        });
-
-        return classes;
-    }
-
-    public List<Class<? extends BasePage>> getPageClasses() {
-        return pages;
+    public List<Class<? extends BasePage>> getIdRepoPageClasses() {
+        return idRepoPages;
     }
 
     public List<Class<? extends BasePage>> getIdMPageClasses() {
@@ -327,20 +283,42 @@ public class ClassPathScanImplementationLookup {
         return amPages;
     }
 
-    public List<Class<? extends BaseExtPage>> getExtPageClasses() {
-        return extPages;
+    @SuppressWarnings("unchecked")
+    public <T> List<Class<? extends T>> getClasses(final Class<T> reference) {
+        return classes.getOrDefault(reference.getName(), List.of()).stream().
+                map(clazz -> (Class<? extends T>) clazz).
+                collect(Collectors.toList());
     }
 
-    public List<Class<? extends BaseExtWidget>> getExtWidgetClasses() {
-        return extWidgets;
+    public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final String mimeType) {
+        LOG.debug("Searching for previewer class for MIME type: {}", mimeType);
+
+        Class<? extends AbstractBinaryPreviewer> previewer = null;
+        for (Class<? extends AbstractBinaryPreviewer> candidate : getClasses(AbstractBinaryPreviewer.class)) {
+            LOG.debug("Evaluating previewer class {} for MIME type {}", candidate.getName(), mimeType);
+            if (candidate.isAnnotationPresent(BinaryPreview.class)
+                    && ArrayUtils.contains(candidate.getAnnotation(BinaryPreview.class).mimeTypes(), mimeType)) {
+                LOG.debug("Found existing previewer for MIME type {}: {}", mimeType, candidate.getName());
+                previewer = candidate;
+            }
+        }
+        return previewer;
     }
 
+    @SuppressWarnings("unchecked")
     public List<Class<? extends ExtAlertWidget<?>>> getExtAlertWidgetClasses() {
-        return extAlertWidgets;
+        return classes.getOrDefault(ExtAlertWidget.class.getName(), List.of()).stream().
+                map(clazz -> (Class<? extends ExtAlertWidget<?>>) clazz).
+                collect(Collectors.toList());
     }
 
-    public List<Class<? extends BaseSSOLoginFormPanel>> getSSOLoginFormPanels() {
-        return ssoLoginFormPanels;
+    @SuppressWarnings("unchecked")
+    public List<Class<? extends UserFormFinalizer>> getUserFormFinalizerClasses(final AjaxWizard.Mode mode) {
+        return classes.getOrDefault(UserFormFinalizer.class.getName(), List.of()).stream().
+                filter(candidate -> candidate.isAnnotationPresent(UserFormFinalize.class)
+                && candidate.getAnnotation(UserFormFinalize.class).mode() == mode).
+                map(clazz -> (Class<? extends UserFormFinalizer>) clazz).
+                collect(Collectors.toList());
     }
 
     public Map<String, Class<? extends ReportletConf>> getReportletConfs() {
@@ -362,8 +340,4 @@ public class ClassPathScanImplementationLookup {
     public Map<String, Class<? extends PushCorrelationRuleConf>> getPushCorrelationRuleConfs() {
         return pushCorrelationRuleConfs;
     }
-
-    public List<Class<? extends AbstractResource>> getResources() {
-        return resources;
-    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 97cfcf6..999630c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -468,7 +468,7 @@ public class BasePage extends BaseWebPage {
         };
         body.add(extAlertWidgets);
 
-        List<Class<? extends BaseExtPage>> extPageClasses = lookup.getExtPageClasses();
+        List<Class<? extends BaseExtPage>> extPageClasses = lookup.getClasses(BaseExtPage.class);
 
         WebMarkupContainer extensionsLI = new WebMarkupContainer(getLIContainerId("extensions"));
         extensionsLI.setOutputMarkupPlaceholderTag(true);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Dashboard.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Dashboard.java
index 1757bf6..fdd1691 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Dashboard.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Dashboard.java
@@ -79,7 +79,7 @@ public class Dashboard extends BasePage {
             }
         });
 
-        List<Class<? extends BaseExtWidget>> extWidgetClasses = lookup.getExtWidgetClasses();
+        List<Class<? extends BaseExtWidget>> extWidgetClasses = lookup.getClasses(BaseExtWidget.class);
         if (!extWidgetClasses.isEmpty()) {
             tabs.add(new AbstractTab(new ResourceModel("extensions")) {
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
index 9009d37..0a664ad 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Login.java
@@ -27,6 +27,7 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.ui.commons.BaseLogin;
 import org.apache.syncope.client.ui.commons.BaseSession;
+import org.apache.syncope.client.ui.commons.panels.BaseSSOLoginFormPanel;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.authentication.IAuthenticationStrategy;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
@@ -53,7 +54,7 @@ public class Login extends BaseLogin {
     @Override
     protected List<Panel> getSSOLoginFormPanels() {
         List<Panel> ssoLoginFormPanels = new ArrayList<>();
-        lookup.getSSOLoginFormPanels().forEach(ssoLoginFormPanel -> {
+        lookup.getClasses(BaseSSOLoginFormPanel.class).forEach(ssoLoginFormPanel -> {
             try {
                 ssoLoginFormPanels.add(ssoLoginFormPanel.getConstructor(String.class, BaseSession.class).newInstance(
                         "ssoLogin", SyncopeConsoleSession.get()));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
index bdb772a..083a41e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
@@ -19,8 +19,13 @@
 package org.apache.syncope.client.console.pages;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.SyncopeWebApplication;
+import org.apache.syncope.client.console.commons.PolicyTabProvider;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
@@ -36,8 +41,14 @@ public class Policies extends BasePage {
         WebMarkupContainer content = new WebMarkupContainer("content");
         content.setOutputMarkupId(true);
         content.setMarkupId("policies");
-        content.add(new AjaxBootstrapTabbedPanel<>(
-                "tabbedPanel", SyncopeWebApplication.get().getPolicyTabProvider().buildTabList(getPageReference())));
+
+        List<ITab> tabs = SyncopeWebApplication.get().getPolicyTabProviders().stream().
+                sorted(Comparator.comparing(PolicyTabProvider::getOrder)).
+                map(p -> p.buildTabList(getPageReference())).
+                flatMap(List::stream).
+                collect(Collectors.toList());
+        content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", tabs));
+
         body.add(content);
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
index 82d1ba2..a7707ac 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
@@ -44,6 +44,7 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPa
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.ui.commons.markup.html.form.AjaxGridFieldPanel;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.Schema;
 import org.apache.syncope.common.lib.report.SearchCondition;
@@ -177,9 +178,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
                     }
 
                     if (listItemType.equals(String.class) && schemaAnnot != null) {
-                        SchemaRestClient schemaRestClient = new SchemaRestClient();
-
-                        final List<SchemaTO> choices = new ArrayList<>();
+                        List<SchemaTO> choices = new ArrayList<>();
 
                         for (SchemaType type : schemaAnnot.type()) {
                             switch (type) {
@@ -219,6 +218,9 @@ public class BeanPanel<T extends Serializable> extends Panel {
                                 fieldName,
                                 buildSinglePanel(bean.getObject(), field.getType(), fieldName, "panel")).hideLabel();
                     }
+                } else if (Map.class.equals(field.getType())) {
+                    panel = new AjaxGridFieldPanel(
+                            "value", fieldName, new PropertyModel<>(bean, fieldName)).hideLabel();
                 } else {
                     panel = buildSinglePanel(bean.getObject(), field.getType(), fieldName, "value").hideLabel();
                 }
@@ -229,11 +231,13 @@ public class BeanPanel<T extends Serializable> extends Panel {
         }.setReuseItems(true).setOutputMarkupId(true));
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @SuppressWarnings("unchecked")
     private static FieldPanel buildSinglePanel(
-        final Serializable bean, final Class<?> type, final String fieldName, final String id) {
-        FieldPanel result = null;
-        PropertyModel model = new PropertyModel(bean, fieldName);
+            final Serializable bean, final Class<?> type, final String fieldName, final String id) {
+
+        PropertyModel model = new PropertyModel<>(bean, fieldName);
+
+        FieldPanel result;
         if (ClassUtils.isAssignable(Boolean.class, type)) {
             result = new AjaxCheckBoxPanel(id, fieldName, model);
         } else if (ClassUtils.isAssignable(Number.class, type)) {
@@ -243,12 +247,9 @@ public class BeanPanel<T extends Serializable> extends Panel {
             result = new AjaxDateTimeFieldPanel(id, fieldName, model,
                     FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
         } else if (type.isEnum()) {
-            result = new AjaxDropDownChoicePanel(id, fieldName, model).setChoices(
-                    List.of(type.getEnumConstants()));
-        }
-
-        // treat as String if nothing matched above
-        if (result == null) {
+            result = new AjaxDropDownChoicePanel(id, fieldName, model).setChoices(List.of(type.getEnumConstants()));
+        } else {
+            // treat as String if nothing matched above
             result = new AjaxTextFieldPanel(id, fieldName, model);
         }
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConfParam.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConfParam.java
index d3b40fd..9b5930e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConfParam.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ConfParam.java
@@ -79,4 +79,13 @@ public class ConfParam implements Serializable {
     public boolean isInstance(final Class<?> clazz) {
         return !values.isEmpty() && clazz.isInstance(values.get(0));
     }
+
+    @Override
+    public String toString() {
+        return "ConfParam{"
+                + "schema=" + schema
+                + ", values=" + values
+                + ", multivalue=" + multivalue
+                + '}';
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
index f4ee95e..9c1c052 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/DynRealmModalPanel.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import java.util.Collections;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -38,7 +37,6 @@ import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.Panel;
@@ -90,7 +88,7 @@ public class DynRealmModalPanel extends AbstractModalPanel<DynRealmWrapper> {
             @Override
             protected void populateItem(final ListItem<AnyTypeTO> item) {
                 final String key = item.getModelObject().getKey();
-                item.add(new Accordion("dynMembershipCond", Collections.<ITab>singletonList(
+                item.add(new Accordion("dynMembershipCond", List.of(
                         new AbstractTab(Model.of(key + " Dynamic Condition")) {
 
                     private static final long serialVersionUID = 1037272333056449378L;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
index 4993f6b..92220e3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
@@ -21,7 +21,6 @@ package org.apache.syncope.client.console.panels;
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -82,9 +81,7 @@ public class ParametersDirectoryPanel
             private static final long serialVersionUID = 1995192603527154740L;
 
             @Override
-            public WizardModalPanel<ConfParam> build(
-                    final String id, final int index, final AjaxWizard.Mode mode) {
-
+            public WizardModalPanel<ConfParam> build(final String id, final int index, final AjaxWizard.Mode mode) {
                 return new ParametersModalPanel(modal, newModelObject(), confParamOps, mode, pageRef);
             }
         }, true);
@@ -108,7 +105,7 @@ public class ParametersDirectoryPanel
 
     @Override
     protected Collection<ActionLink.ActionType> getBatches() {
-        return Collections.<ActionLink.ActionType>singletonList(ActionLink.ActionType.DELETE);
+        return List.of();
     }
 
     @Override
@@ -147,7 +144,6 @@ public class ParametersDirectoryPanel
             @Override
             public void onClick(final AjaxRequestTarget target, final ConfParam ignore) {
                 target.add(modal);
-                // modal.addSubmitButton();
                 modal.header(new StringResourceModel("any.edit"));
                 modal.setContent(new ParametersModalPanel(
                         modal, model.getObject(), confParamOps, AjaxWizard.Mode.EDIT, pageRef));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java
index 84c44e7..56986f4 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java
@@ -29,6 +29,7 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPa
 import org.apache.syncope.client.console.wicket.markup.html.form.BinaryFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
+import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.wicket.extensions.wizard.WizardStep;
@@ -48,7 +49,10 @@ public class ParametersWizardAttrStep extends WizardStep {
 
     private final AjaxTextFieldPanel schema;
 
-    public ParametersWizardAttrStep(final ParametersWizardPanel.ParametersForm modelObject) {
+    public ParametersWizardAttrStep(
+            final AjaxWizard.Mode mode,
+            final ParametersWizardPanel.ParametersForm modelObject) {
+
         this.setOutputMarkupId(true);
 
         WebMarkupContainer content = new WebMarkupContainer("content");
@@ -58,10 +62,10 @@ public class ParametersWizardAttrStep extends WizardStep {
         schema = new AjaxTextFieldPanel(
                 "schema", getString("schema"), new PropertyModel<>(modelObject.getParam(), "schema"));
         schema.setRequired(true);
+        schema.setReadOnly(mode != AjaxWizard.Mode.CREATE);
         content.add(schema);
 
-        LoadableDetachableModel<List<PlainSchemaTO>> loadableDetachableModel =
-                new LoadableDetachableModel<List<PlainSchemaTO>>() {
+        LoadableDetachableModel<List<PlainSchemaTO>> schemas = new LoadableDetachableModel<List<PlainSchemaTO>>() {
 
             private static final long serialVersionUID = 7172461137064525667L;
 
@@ -71,23 +75,21 @@ public class ParametersWizardAttrStep extends WizardStep {
             }
         };
 
-        ListView<PlainSchemaTO> listView = new ListView<PlainSchemaTO>("attrs", loadableDetachableModel) {
+        ListView<PlainSchemaTO> attrs = new ListView<PlainSchemaTO>("attrs", schemas) {
 
             private static final long serialVersionUID = 9101744072914090143L;
 
             @Override
             protected void populateItem(final ListItem<PlainSchemaTO> item) {
-                final Panel panel = getFieldPanel("panel", modelObject.getParam(), item.getModelObject());
-                item.add(panel);
+                item.add(getFieldPanel("panel", modelObject.getParam(), item.getModelObject()));
             }
         };
-
-        content.add(listView);
+        content.add(attrs);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private Panel getFieldPanel(final String id, final ConfParam param, final PlainSchemaTO plainSchemaTO) {
-        final String valueHeaderName = getString("values");
+        String valueHeaderName = getString("values");
 
         final FieldPanel panel;
         switch (plainSchemaTO.getType()) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardPanel.java
index 043ba14..2917c46 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardPanel.java
@@ -42,7 +42,7 @@ public class ParametersWizardPanel extends BaseAjaxWizardBuilder<ParametersWizar
     @Override
     protected WizardModel buildModelSteps(final ParametersForm modelObject, final WizardModel wizardModel) {
         wizardModel.add(new ParametersWizardSchemaStep(modelObject));
-        wizardModel.add(new ParametersWizardAttrStep(modelObject));
+        wizardModel.add(new ParametersWizardAttrStep(mode, modelObject));
         return wizardModel;
     }
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
index 4ae1bf4..3048369 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
@@ -18,34 +18,28 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.SyncopeWebApplication;
+import org.apache.syncope.client.console.commons.RealmPolicyProvider;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
-import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
-import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.form.DropDownChoice;
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.RepeatingView;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.util.ListModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,28 +49,6 @@ public class RealmDetails extends Panel {
 
     protected static final Logger LOG = LoggerFactory.getLogger(RealmDetails.class);
 
-    private final IModel<Map<String, String>> accountPolicies = new LoadableDetachableModel<Map<String, String>>() {
-
-        private static final long serialVersionUID = -2012833443695917883L;
-
-        @Override
-        protected Map<String, String> load() {
-            return PolicyRestClient.getPolicies(PolicyType.ACCOUNT).stream().
-                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
-        }
-    };
-
-    private final IModel<Map<String, String>> passwordPolicies = new LoadableDetachableModel<Map<String, String>>() {
-
-        private static final long serialVersionUID = -2012833443695917883L;
-
-        @Override
-        protected Map<String, String> load() {
-            return PolicyRestClient.getPolicies(PolicyType.PASSWORD).stream().
-                    collect(Collectors.toMap(PolicyTO::getKey, PolicyTO::getDescription));
-        }
-    };
-
     private final IModel<List<String>> logicActions = new LoadableDetachableModel<List<String>>() {
 
         private static final long serialVersionUID = 5275935387613157437L;
@@ -98,6 +70,9 @@ public class RealmDetails extends Panel {
         }
     };
 
+    @SpringBean
+    private RealmPolicyProvider realmPolicyProvider;
+
     private final WebMarkupContainer container;
 
     public RealmDetails(final String id, final RealmTO realmTO) {
@@ -130,25 +105,9 @@ public class RealmDetails extends Panel {
         fullPath.setEnabled(false);
         generics.add(fullPath);
 
-        AjaxDropDownChoicePanel<String> accountPolicy = new AjaxDropDownChoicePanel<>(
-                "accountPolicy",
-                new ResourceModel("accountPolicy", "accountPolicy").getObject(),
-                new PropertyModel<>(realmTO, "accountPolicy"),
-                false);
-        accountPolicy.setChoiceRenderer(new PolicyRenderer(accountPolicies));
-        accountPolicy.setChoices(new ArrayList<>(accountPolicies.getObject().keySet()));
-        ((DropDownChoice<?>) accountPolicy.getField()).setNullValid(true);
-        container.add(accountPolicy);
-
-        AjaxDropDownChoicePanel<String> passwordPolicy = new AjaxDropDownChoicePanel<>(
-                "passwordPolicy",
-                new ResourceModel("passwordPolicy", "passwordPolicy").getObject(),
-                new PropertyModel<>(realmTO, "passwordPolicy"),
-                false);
-        passwordPolicy.setChoiceRenderer(new PolicyRenderer(passwordPolicies));
-        passwordPolicy.setChoices(new ArrayList<>(passwordPolicies.getObject().keySet()));
-        ((DropDownChoice<?>) passwordPolicy.getField()).setNullValid(true);
-        container.add(passwordPolicy);
+        RepeatingView policies = new RepeatingView("policies");
+        realmPolicyProvider.add(realmTO, policies);
+        container.add(policies);
 
         AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>().
                 setAllowMoveAll(true).setAllowOrder(true).
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index 7c931cf..c2df030 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -22,7 +22,6 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import org.apache.commons.lang3.SerializationUtils;
@@ -261,7 +260,7 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
 
     @Override
     protected Collection<ActionLink.ActionType> getBatches() {
-        return Collections.<ActionLink.ActionType>singletonList(ActionLink.ActionType.DELETE);
+        return List.of(ActionLink.ActionType.DELETE);
     }
 
     public abstract static class Builder
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java
index eac8db2..67b3056 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.java
@@ -112,8 +112,10 @@ public abstract class PolicyDirectoryPanel<T extends PolicyTO>
                 new StringResourceModel(Constants.KEY_FIELD_NAME, this), Constants.KEY_FIELD_NAME));
         columns.add(new PropertyColumn<>(
                 new StringResourceModel("description", this), "description", "description"));
-        columns.add(new CollectionPropertyColumn<>(
-                new StringResourceModel("usedByResources", this), "usedByResources"));
+        if (type != PolicyType.ACCESS && type != PolicyType.ATTR_RELEASE && type != PolicyType.AUTH) {
+            columns.add(new CollectionPropertyColumn<>(
+                    new StringResourceModel("usedByResources", this), "usedByResources"));
+        }
         if (type != PolicyType.PULL && type != PolicyType.PUSH) {
             columns.add(new CollectionPropertyColumn<>(
                     new StringResourceModel("usedByRealms", this), "usedByRealms"));
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
index dace20d..be9bbe8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
@@ -135,7 +135,7 @@ public class ReportletWizardBuilder extends BaseAjaxWizardBuilder<ReportletWrapp
         private static final long serialVersionUID = -785981096328637758L;
 
         public Configuration(final ReportletWrapper reportlet) {
-            final LoadableDetachableModel<Serializable> bean = new LoadableDetachableModel<Serializable>() {
+            LoadableDetachableModel<Serializable> bean = new LoadableDetachableModel<Serializable>() {
 
                 private static final long serialVersionUID = 2092144708018739371L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
index 78032c2..11a4c6b 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/PolicyRestClient.java
@@ -76,9 +76,9 @@ public class PolicyRestClient extends BaseRestClient {
 
         @Override
         public int compare(final PolicyTO left, final PolicyTO right) {
-            return Optional.ofNullable(left).map(to -> Optional.ofNullable(right)
-                .map(policyTO -> to.getDescription().compareTo(policyTO.getDescription())).orElse(1)).orElse(-1);
+            return Optional.ofNullable(left).map(to -> Optional.ofNullable(right).
+                    map(policyTO -> to.getDescription().compareTo(policyTO.getDescription())).orElse(1)).
+                    orElse(-1);
         }
-
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java
index 354a835..5a0e02c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskFilters.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.tasks;
 
-import java.util.Collections;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
@@ -27,7 +26,6 @@ import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
@@ -60,7 +58,7 @@ public class PushTaskFilters extends WizardStep {
             @Override
             protected void populateItem(final ListItem<AnyTypeTO> item) {
                 final String key = item.getModelObject().getKey();
-                item.add(new Accordion("filters", Collections.<ITab>singletonList(
+                item.add(new Accordion("filters", List.of(
                         new AbstractTab(new StringResourceModel(
                                 "filters", this, new Model<>(item.getModelObject()))) {
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java
index 47e4de4..46d68b0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/TemplatesTogglePanel.java
@@ -79,7 +79,7 @@ public abstract class TemplatesTogglePanel extends TogglePanel<Serializable> {
         form = new Form<>("templatesForm");
         addInnerObject(form);
 
-        final FieldPanel<String> type = new AjaxDropDownChoicePanel<>("type", "type", typeModel, false).
+        FieldPanel<String> type = new AjaxDropDownChoicePanel<>("type", "type", typeModel, false).
                 setChoices(anyTypes).
                 setStyleSheet("form-control").
                 setRequired(true);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
index 257a824..40c4487 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DerAttrs.java
@@ -18,9 +18,7 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -30,6 +28,7 @@ import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
@@ -38,7 +37,6 @@ import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -62,7 +60,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
         super(modelObject, AjaxWizard.Mode.CREATE, anyTypeClasses, whichDerAttrs);
         setTitleModel(new ResourceModel("attributes.derived"));
 
-        add(new Accordion("derSchemas", Collections.<ITab>singletonList(new AbstractTab(
+        add(new Accordion("derSchemas", List.of(new AbstractTab(
                 new ResourceModel("attributes.accordion", "Derived Attributes")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
@@ -80,7 +78,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
             @Override
             protected void populateItem(final ListItem<MembershipTO> item) {
                 final MembershipTO membershipTO = item.getModelObject();
-                item.add(new Accordion("membershipDerSchemas", Collections.<ITab>singletonList(new AbstractTab(
+                item.add(new Accordion("membershipDerSchemas", List.of(new AbstractTab(
                         new StringResourceModel(
                                 "attributes.membership.accordion",
                                 DerAttrs.this,
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
index daca2c9..ec0f11e 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/DynamicMemberships.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
@@ -30,7 +29,6 @@ import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Ac
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
@@ -63,7 +61,7 @@ public class DynamicMemberships extends WizardStep {
         // ------------------------
         // uDynMembershipCond
         // ------------------------
-        add(new Accordion("uDynMembershipCond", Collections.<ITab>singletonList(
+        add(new Accordion("uDynMembershipCond", List.of(
                 new AbstractTab(new ResourceModel("uDynMembershipCond", "Dynamic USER Membership Conditions")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
@@ -86,7 +84,7 @@ public class DynamicMemberships extends WizardStep {
             @Override
             protected void populateItem(final ListItem<AnyTypeTO> item) {
                 final String key = item.getModelObject().getKey();
-                item.add(new Accordion("aDynMembershipCond", Collections.<ITab>singletonList(
+                item.add(new Accordion("aDynMembershipCond", List.of(
                         new AbstractTab(new StringResourceModel(
                                 "aDynMembershipCond", this, new Model<AnyTypeTO>(item.getModelObject()))) {
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
index 48e7ed1..0a6c257 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserDetails.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
+import java.util.List;
 import org.apache.syncope.client.ui.commons.wizards.any.PasswordPanel;
-import java.util.Collections;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo;
 import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
@@ -79,9 +79,9 @@ public class UserDetails extends Details<UserTO> {
         // ------------------------
         // Password
         // ------------------------
-        final Model<Integer> model = Model.of(-1);
+        Model<Integer> model = Model.of(-1);
 
-        final Accordion accordion = new Accordion("accordionPanel", Collections.<ITab>singletonList(
+        Accordion accordion = new Accordion("accordionPanel", List.of(
                 new AbstractTab(new ResourceModel("password.change", "Change password")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
index 8f356d5..2c81950 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/VirAttrs.java
@@ -21,7 +21,6 @@ package org.apache.syncope.client.console.wizards.any;
 import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -42,7 +41,6 @@ import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
@@ -57,8 +55,6 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
 
     private static final long serialVersionUID = -7982691107029848579L;
 
-    private final AjaxWizard.Mode mode;
-
     private final AnyWrapper<?> modelObject;
 
     public <T extends AnyTO> VirAttrs(
@@ -68,12 +64,11 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
             final List<String> whichVirAttrs) {
 
         super(modelObject, mode, anyTypeClasses, whichVirAttrs);
-        this.mode = mode;
         this.modelObject = modelObject;
 
         setTitleModel(new ResourceModel("attributes.virtual"));
 
-        add(new Accordion("virSchemas", Collections.<ITab>singletonList(new AbstractTab(
+        add(new Accordion("virSchemas", List.of(new AbstractTab(
                 new ResourceModel("attributes.accordion", "Virtual Attributes")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
@@ -90,21 +85,20 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
 
             @Override
             protected void populateItem(final ListItem<MembershipTO> item) {
-                final MembershipTO membershipTO = item.getModelObject();
-                item.add(new Accordion("membershipVirSchemas",
-                        Collections.<ITab>singletonList(new AbstractTab(new StringResourceModel(
-                                "attributes.membership.accordion", VirAttrs.this, Model.of(membershipTO))) {
-
-                            private static final long serialVersionUID = 1037272333056449378L;
-
-                            @Override
-                            public WebMarkupContainer getPanel(final String panelId) {
-                                return new VirAttrs.VirSchemas(
-                                        panelId,
-                                        membershipSchemas.get(membershipTO.getGroupKey()),
-                                        new ListModel<>(getAttrsFromTO(membershipTO)));
-                            }
-                        }), Model.of(-1)).setOutputMarkupId(true));
+                MembershipTO membTO = item.getModelObject();
+                item.add(new Accordion("membershipVirSchemas", List.of(new AbstractTab(
+                        new StringResourceModel("attributes.membership.accordion", VirAttrs.this, Model.of(membTO))) {
+
+                    private static final long serialVersionUID = 1037272333056449378L;
+
+                    @Override
+                    public WebMarkupContainer getPanel(final String panelId) {
+                        return new VirAttrs.VirSchemas(
+                                panelId,
+                                membershipSchemas.get(membTO.getGroupKey()),
+                                new ListModel<>(getAttrsFromTO(membTO)));
+                    }
+                }), Model.of(-1)).setOutputMarkupId(true));
             }
         });
     }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.java
index 127b7ca..f7295d8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.java
@@ -58,10 +58,16 @@ public abstract class AbstractMappingPanel extends Panel {
      */
     protected final AnyTypeClassRestClient anyTypeClassRestClient = new AnyTypeClassRestClient();
 
+    protected final Label connObjectKeyLabel;
+
     protected final Label passwordLabel;
 
     protected final Label purposeLabel;
 
+    protected final Label intAttrNameInfo;
+
+    protected final WebMarkupContainer mandatoryHeader;
+
     /**
      * Add mapping button.
      */
@@ -83,7 +89,6 @@ public abstract class AbstractMappingPanel extends Panel {
             final JEXLTransformersTogglePanel jexlTransformers,
             final IModel<List<ItemTO>> model,
             final boolean addMappingBtnVisible,
-            final boolean hidePurpose,
             final MappingPurpose defaultPurpose) {
 
         super(id);
@@ -93,14 +98,22 @@ public abstract class AbstractMappingPanel extends Panel {
         mappingContainer.setOutputMarkupId(true);
         add(mappingContainer);
 
+        mappingContainer.add(new Label("itemTransformersLabel", Model.of()).setVisible(itemTransformers != null));
+
+        mappingContainer.add(new Label("jexlTransformersLabel", Model.of()).setVisible(jexlTransformers != null));
+
+        connObjectKeyLabel = new Label("connObjectKeyLabel", new ResourceModel("connObjectKey"));
+        mappingContainer.add(connObjectKeyLabel);
+
         passwordLabel = new Label("passwordLabel", new ResourceModel("password"));
         mappingContainer.add(passwordLabel);
 
         purposeLabel = new Label("purposeLabel", new ResourceModel("purpose"));
         mappingContainer.add(purposeLabel);
 
-        mappingContainer.add(new Label("intAttrNameInfo", Model.of()).add(new PopoverBehavior(
-                Model.<String>of(),
+        intAttrNameInfo = new Label("intAttrNameInfo", Model.of());
+        intAttrNameInfo.add(new PopoverBehavior(
+                Model.of(),
                 Model.of(getString("intAttrNameInfo.help")
                         + "<code>groups[groupName].attribute</code>, "
                         + "<code>users[userName].attribute</code>, "
@@ -116,9 +129,13 @@ public abstract class AbstractMappingPanel extends Panel {
             protected String createRelAttribute() {
                 return "intAttrNameInfo";
             }
-        }));
+        });
+        mappingContainer.add(intAttrNameInfo);
 
-        mappingContainer.add(Constants.getJEXLPopover(this, TooltipConfig.Placement.bottom));
+        mandatoryHeader = new WebMarkupContainer("mandatoryHeader");
+        mandatoryHeader.setOutputMarkupId(true);
+        mandatoryHeader.add(Constants.getJEXLPopover(this, TooltipConfig.Placement.bottom));
+        mappingContainer.add(mandatoryHeader);
 
         model.getObject().sort((left, right) -> {
             int compared;
@@ -141,17 +158,17 @@ public abstract class AbstractMappingPanel extends Panel {
             } else if (left.getPurpose() != MappingPurpose.BOTH && right.getPurpose() == MappingPurpose.BOTH) {
                 compared = 1;
             } else if (left.getPurpose() == MappingPurpose.PROPAGATION
-                && (right.getPurpose() == MappingPurpose.PULL
-                || right.getPurpose() == MappingPurpose.NONE)) {
+                    && (right.getPurpose() == MappingPurpose.PULL
+                    || right.getPurpose() == MappingPurpose.NONE)) {
                 compared = -1;
             } else if (left.getPurpose() == MappingPurpose.PULL
-                && right.getPurpose() == MappingPurpose.PROPAGATION) {
+                    && right.getPurpose() == MappingPurpose.PROPAGATION) {
                 compared = 1;
             } else if (left.getPurpose() == MappingPurpose.PULL
-                && right.getPurpose() == MappingPurpose.NONE) {
+                    && right.getPurpose() == MappingPurpose.NONE) {
                 compared = -1;
             } else if (left.getPurpose() == MappingPurpose.NONE
-                && right.getPurpose() != MappingPurpose.NONE) {
+                    && right.getPurpose() != MappingPurpose.NONE) {
                 compared = 1;
             } else {
                 compared = left.getIntAttrName().compareTo(right.getIntAttrName());
@@ -201,15 +218,24 @@ public abstract class AbstractMappingPanel extends Panel {
                 //--------------------------------
                 // JEXL transformers
                 // -------------------------------
-                item.add(new JEXLTransformerWidget(
-                        "jexlTransformers", itemTO, jexlTransformers).setRenderBodyOnly(true));
+                if (jexlTransformers == null) {
+                    item.add(new Label("jexlTransformers").setVisible(false));
+                } else {
+                    item.add(new JEXLTransformerWidget(
+                            "jexlTransformers", itemTO, jexlTransformers).setRenderBodyOnly(true));
+                }
                 // -------------------------------
 
                 //--------------------------------
                 // Mapping item transformers
                 // -------------------------------
-                item.add(new ItemTransformerWidget(
-                        "itemTransformers", itemTO, itemTransformers).setRenderBodyOnly(true));
+                if (itemTransformers == null) {
+                    item.add(new Label("itemTransformers").setVisible(false));
+
+                } else {
+                    item.add(new ItemTransformerWidget(
+                            "itemTransformers", itemTO, itemTransformers).setRenderBodyOnly(true));
+                }
                 // -------------------------------
 
                 //--------------------------------
@@ -337,9 +363,11 @@ public abstract class AbstractMappingPanel extends Panel {
                     itemTO.setPassword(false);
                 }
 
-                if (hidePurpose) {
-                    purpose.setVisible(false);
-                }
+                purpose.setVisible(!hidePurpose());
+
+                mandatory.setVisible(!hideMandatory());
+
+                connObjectKey.setVisible(!hideConnObjectKey());
             }
         };
 
@@ -359,13 +387,34 @@ public abstract class AbstractMappingPanel extends Panel {
         addMappingBtn.setDefaultFormProcessing(false);
         addMappingBtn.setEnabled(addMappingBtnVisible);
         mappingContainer.add(addMappingBtn);
+    }
 
+    @Override
+    protected void onBeforeRender() {
+        super.onBeforeRender();
+
+        passwordLabel.setVisible(!hidePassword());
+        purposeLabel.setVisible(!hidePurpose());
+        mandatoryHeader.setVisible(!hideMandatory());
+        connObjectKeyLabel.setVisible(!hideConnObjectKey());
     }
 
     protected boolean hidePassword() {
         return true;
     }
 
+    protected boolean hidePurpose() {
+        return false;
+    }
+
+    protected boolean hideMandatory() {
+        return false;
+    }
+
+    protected boolean hideConnObjectKey() {
+        return false;
+    }
+
     protected abstract IModel<List<String>> getExtAttrNames();
 
     /**
@@ -375,13 +424,6 @@ public abstract class AbstractMappingPanel extends Panel {
      */
     protected abstract void setAttrNames(AjaxTextFieldPanel toBeUpdated);
 
-    @Override
-    protected void onBeforeRender() {
-        super.onBeforeRender();
-        passwordLabel.setVisible(false);
-        purposeLabel.setVisible(true);
-    }
-
     /**
      * Enable/Disable connObjectKey checkbox.
      *
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java
index 3084490..ddd027a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/role/RoleWizardBuilder.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.console.wizards.role;
 
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
@@ -40,7 +39,6 @@ import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.extensions.wizard.WizardModel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.panel.Panel;
@@ -113,7 +111,7 @@ public class RoleWizardBuilder extends BaseAjaxWizardBuilder<RoleWrapper> {
             // ------------------------
             // dynMembershipCond
             // ------------------------
-            add(new Accordion("dynMembershipCond", Collections.<ITab>singletonList(
+            add(new Accordion("dynMembershipCond", List.of(
                     new AbstractTab(new ResourceModel("dynMembershipCond", "Dynamic USER Membership Conditions")) {
 
                 private static final long serialVersionUID = 1037272333056449378L;
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies.properties
index b8dd372..8f9914e 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies.properties
@@ -18,3 +18,6 @@ policy.account=Account
 policy.password=Password
 policy.pull=Pull
 policy.push=Push
+policy.access=Access
+policy.attrRelease=Attribute Release
+policy.auth=Authentication
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
index b8dd372..1d36635 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_it.properties
@@ -18,3 +18,6 @@ policy.account=Account
 policy.password=Password
 policy.pull=Pull
 policy.push=Push
+policy.access=Accesso
+policy.attrRelease=Rilascio Attributi
+policy.auth=Autenticazione
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ja.properties
index db61808..c998c1a 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ja.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ja.properties
@@ -18,3 +18,6 @@ policy.account=\u30a2\u30ab\u30a6\u30f3\u30c8
 policy.password=\u30d1\u30b9\u30ef\u30fc\u30c9
 policy.pull=\u30d7\u30eb
 policy.push=\u30d7\u30c3\u30b7\u30e5
+policy.access=Access
+policy.attrRelease=Attribute Release
+policy.auth=Authentication
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_pt_BR.properties
index b8dd372..8f9914e 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_pt_BR.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_pt_BR.properties
@@ -18,3 +18,6 @@ policy.account=Account
 policy.password=Password
 policy.pull=Pull
 policy.push=Push
+policy.access=Access
+policy.attrRelease=Attribute Release
+policy.auth=Authentication
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ru.properties
index 5c1a92a..6d42c42 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ru.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/pages/Policies_ru.properties
@@ -19,3 +19,6 @@ policy.account=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u0443\u0447\u04
 policy.password=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043f\u0430\u0440\u043e\u043b\u0435\u0439
 policy.pull=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445
 policy.push=Push
+policy.access=Access
+policy.attrRelease=Attribute Release
+policy.auth=Authentication
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties
index a0b9e8a..788dbfd 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/ParametersDirectoryPanel_fr_CA.properties
@@ -14,8 +14,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-any.edit=Modifier param�tre ${key}
-any.new=Nouveau param�tre
+any.edit=Modifier param\u00e8tre ${key}
+any.new=Nouveau param\u00e8tre
 values=Valeurs
 readonly=Lecture seulement
-any.edit=Modifier param�tre
+any.edit=Modifier param\u00e8tre
+tooLong=Value too long to be displayed
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.html
index b914e73..13c074f 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.html
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.html
@@ -28,10 +28,7 @@ under the License.
         </div>
       </div>
       <div class="form-group">
-        <span wicket:id="accountPolicy">[accountPolicy]</span>
-      </div>
-      <div class="form-group">
-        <span wicket:id="passwordPolicy">[passwordPolicy]</span>
+        <span wicket:id="policies">[policies]</span>
       </div>
       <div class="form-group form-palette">
         <div class="row" wicket:id="actions">[actions]</div>
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.properties
index 5b76f1c..71cf88d 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.properties
@@ -19,3 +19,6 @@ accountPolicy=Account Policy
 passwordPolicy=Password Policy
 actions=Actions
 resources=Assigned resources
+authPolicy=Authentication Policy
+accessPolicy=Access Policy
+attrReleasePolicy=Attribute Release Policy
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_fr_CA.properties
index 5867b1d..61d6e58 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_fr_CA.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_fr_CA.properties
@@ -14,8 +14,11 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-fullPath=Chemin d'acc�s
+fullPath=Chemin d'acc\u00e8s
 accountPolicy=Politique compte
 passwordPolicy=Politique mot de passe
 actions=Actions
-resources=Ressources assign�es
+resources=Ressources assign\u00e9es
+authPolicy=Authentication Policy
+accessPolicy=Access Policy
+attrReleasePolicy=Attribute Release Policy
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_it.properties
index 68d5316..5c053cf 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_it.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_it.properties
@@ -15,7 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 fullPath=Percorso
-accountPolicy=Account Policy
-passwordPolicy=Password Policy
+accountPolicy=Politica Account
+passwordPolicy=Politica Password
 actions=Azioni
 resources=Risorse assegnate
+authPolicy=Politica Autenticazione
+accessPolicy=Politica Accesso
+attrReleasePolicy=Politica Rilascio Attributi
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ja.properties
index 0b1d848..62242de 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ja.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ja.properties
@@ -19,3 +19,6 @@ accountPolicy=\u30a2\u30ab\u30a6\u30f3\u30c8\u30dd\u30ea\u30b7\u30fc
 passwordPolicy=\u30d1\u30b9\u30ef\u30fc\u30c9\u30dd\u30ea\u30b7\u30fc
 actions=\u30a2\u30af\u30b7\u30e7\u30f3
 resources=\u5272\u308a\u5f53\u3066\u3089\u308c\u305f\u30ea\u30bd\u30fc\u30b9
+authPolicy=Authentication Policy
+accessPolicy=Access Policy
+attrReleasePolicy=Attribute Release Policy
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_pt_BR.properties
index 43092e5..7862d3e 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_pt_BR.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_pt_BR.properties
@@ -19,3 +19,6 @@ accountPolicy=Pol\u00edtica de Conta
 passwordPolicy=Pol\u00edtica de Senha
 actions=Actions
 resources=Assigned resources
+authPolicy=Authentication Policy
+accessPolicy=Access Policy
+attrReleasePolicy=Attribute Release Policy
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ru.properties
index 67a7bcb..83d69a3 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ru.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ru.properties
@@ -20,3 +20,6 @@ accountPolicy=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u0443\u0447\u043
 passwordPolicy=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043f\u0430\u0440\u043e\u043b\u0435\u0439
 actions=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f
 resources=\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b
+authPolicy=Authentication Policy
+accessPolicy=Access Policy
+attrReleasePolicy=Attribute Release Policy
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.html
index 21d117f..229c27f 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.html
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/mapping/AbstractMappingPanel.html
@@ -30,13 +30,13 @@ under the License.
               <span id="intAttrNameInfo" wicket:id="intAttrNameInfo" class="fas fa-info-circle"></span>
             </th>
             <th><wicket:message key="extAttrName"/></th>
-            <th><i class="fas fa-redo-alt"></i></th>
-            <th><i class="fa fa-magic"></i></th>
-            <th>
+            <th><i wicket:id="itemTransformersLabel" class="fas fa-redo-alt"></i></th>
+            <th><i wicket:id="jexlTransformersLabel" class="fa fa-magic"></i></th>
+            <th wicket:id="mandatoryHeader">
               <wicket:message key="mandatoryCondition"/>
               <span id="jexlInfo" wicket:id="jexlInfo" class="fas fa-info-circle"></span>
             </th>
-            <th><wicket:message key="connObjectKey"/></th>
+            <th><label wicket:id="connObjectKeyLabel"/></th>
             <th><label wicket:id="passwordLabel"/></th>
             <th><label wicket:id="purposeLabel"/></th>
             <th></th>
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
index 1494482..7ce5c43 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/AnyWizardBuilder.java
@@ -126,8 +126,7 @@ public abstract class AnyWizardBuilder extends AbstractAnyWizardBuilder<UserTO>
             wizardModel.add(new DerAttrs(modelObject, anyTypeClasses, formLayoutInfo.getWhichDerAttrs()));
         }
         if (formLayoutInfo.isVirAttrs()) {
-            wizardModel.add(new VirAttrs(
-                    modelObject, mode, anyTypeClasses, formLayoutInfo.getWhichVirAttrs()));
+            wizardModel.add(new VirAttrs(modelObject, anyTypeClasses, formLayoutInfo.getWhichVirAttrs()));
         }
         if (formLayoutInfo.isResources()) {
             wizardModel.add(new Resources(modelObject));
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
index 9940a44..952b834 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/DerAttrs.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.enduser.wizards.any;
 
 import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -38,7 +37,6 @@ import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -62,7 +60,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
         super(modelObject, anyTypeClasses, whichDerAttrs);
         setTitleModel(new ResourceModel("attributes.derived"));
 
-        add(new Accordion("derSchemas", Collections.<ITab>singletonList(new AbstractTab(
+        add(new Accordion("derSchemas", List.of(new AbstractTab(
                 new ResourceModel("attributes.accordion", "Derived Attributes")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
@@ -80,7 +78,7 @@ public class DerAttrs extends AbstractAttrs<DerSchemaTO> {
             @Override
             protected void populateItem(final ListItem<MembershipTO> item) {
                 final MembershipTO membershipTO = item.getModelObject();
-                item.add(new Accordion("membershipDerSchemas", Collections.<ITab>singletonList(new AbstractTab(
+                item.add(new Accordion("membershipDerSchemas", List.of(new AbstractTab(
                         new StringResourceModel(
                                 "attributes.membership.accordion",
                                 DerAttrs.this,
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
index 7e1e66f..281ca92 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/PlainAttrs.java
@@ -18,10 +18,9 @@
  */
 package org.apache.syncope.client.enduser.wizards.any;
 
+import java.util.ArrayList;
 import org.apache.syncope.client.ui.commons.wizards.any.UserWrapper;
 import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,7 +57,6 @@ import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.markup.html.list.ListItem;
@@ -106,7 +104,7 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
         setTitleModel(new ResourceModel("attributes.plain"));
 
-        add(new Accordion("plainSchemas", Collections.<ITab>singletonList(new AbstractTab(
+        add(new Accordion("plainSchemas", List.of(new AbstractTab(
                 new ResourceModel("attributes.accordion", "Plain Attributes")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
@@ -119,12 +117,12 @@ public class PlainAttrs extends AbstractAttrs<PlainSchemaTO> {
 
         add(new ListView<MembershipTO>("membershipsPlainSchemas", membershipTOs) {
 
-            private static final long serialVersionUID = 1L;
+            private static final long serialVersionUID = 1749643897846L;
 
             @Override
             protected void populateItem(final ListItem<MembershipTO> item) {
                 final MembershipTO membershipTO = item.getModelObject();
-                item.add(new Accordion("membershipPlainSchemas", Collections.<ITab>singletonList(new AbstractTab(
+                item.add(new Accordion("membershipPlainSchemas", List.of(new AbstractTab(
                         new StringResourceModel(
                                 "attributes.membership.accordion",
                                 PlainAttrs.this,
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
index 11b61ff..fdc6ccc 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/UserDetails.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.enduser.wizards.any;
 
 import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthBehavior;
 import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.password.strength.PasswordStrengthConfig;
-import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
@@ -110,9 +109,9 @@ public class UserDetails extends WizardStep {
         // ------------------------
         // Password
         // ------------------------
-        final Model<Integer> model = Model.of(-1);
+        Model<Integer> model = Model.of(-1);
 
-        final Accordion accordion = new Accordion("accordionPanel", Collections.<ITab>singletonList(
+        Accordion accordion = new Accordion("accordionPanel", List.of(
                 new AbstractTab(new ResourceModel("password.change", "Change password")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
diff --git a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
index 8a3b974..86c55b2 100644
--- a/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
+++ b/client/idrepo/enduser/src/main/java/org/apache/syncope/client/enduser/wizards/any/VirAttrs.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.enduser.wizards.any;
 
 import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -32,7 +31,6 @@ import org.apache.syncope.client.enduser.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
 import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.Attr;
@@ -41,7 +39,6 @@ import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
@@ -56,23 +53,16 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
 
     private static final long serialVersionUID = -7982691107029848579L;
 
-    private final AjaxWizard.Mode mode;
-
-    private final AnyWrapper<?> modelObject;
-
     public <T extends AnyTO> VirAttrs(
             final AnyWrapper<T> modelObject,
-            final AjaxWizard.Mode mode,
             final List<String> anyTypeClasses,
             final Map<String, CustomizationOption> whichVirAttrs) {
 
         super(modelObject, anyTypeClasses, whichVirAttrs);
-        this.mode = mode;
-        this.modelObject = modelObject;
 
         setTitleModel(new ResourceModel("attributes.virtual"));
 
-        add(new Accordion("virSchemas", Collections.<ITab>singletonList(new AbstractTab(
+        add(new Accordion("virSchemas", List.of(new AbstractTab(
                 new ResourceModel("attributes.accordion", "Virtual Attributes")) {
 
             private static final long serialVersionUID = 1037272333056449378L;
@@ -89,22 +79,21 @@ public class VirAttrs extends AbstractAttrs<VirSchemaTO> {
 
             @Override
             protected void populateItem(final ListItem<MembershipTO> item) {
-                final MembershipTO membershipTO = item.getModelObject();
-                item.add(new Accordion("membershipVirSchemas",
-                        Collections.<ITab>singletonList(new AbstractTab(new StringResourceModel(
-                                "attributes.membership.accordion", VirAttrs.this, Model.of(membershipTO))) {
-
-                            private static final long serialVersionUID = 1037272333056449378L;
-
-                            @Override
-                            public WebMarkupContainer getPanel(final String panelId) {
-                                return new VirAttrs.VirSchemas(
-                                        panelId,
-                                        membershipTO.getGroupName(),
-                                        membershipSchemas.get(membershipTO.getGroupKey()),
-                                        new ListModel<>(getAttrsFromTO(membershipTO)));
-                            }
-                        }), Model.of(-1)).setOutputMarkupId(true));
+                MembershipTO membTO = item.getModelObject();
+                item.add(new Accordion("membershipVirSchemas", List.of(new AbstractTab(
+                        new StringResourceModel("attributes.membership.accordion", VirAttrs.this, Model.of(membTO))) {
+
+                    private static final long serialVersionUID = 1037272333056449378L;
+
+                    @Override
+                    public WebMarkupContainer getPanel(final String panelId) {
+                        return new VirAttrs.VirSchemas(
+                                panelId,
+                                membTO.getGroupName(),
+                                membershipSchemas.get(membTO.getGroupKey()),
+                                new ListModel<>(getAttrsFromTO(membTO)));
+                    }
+                }), Model.of(-1)).setOutputMarkupId(true));
             }
         });
     }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/DuoMfaAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/DuoMfaAuthModuleConf.java
index 15a4909..146cfcd 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/DuoMfaAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/DuoMfaAuthModuleConf.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib.auth;
 
-public class DuoMfaAuthModuleConf extends AbstractAuthModuleConf {
+public class DuoMfaAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -2883257599439312426L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleMfaAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleMfaAuthModuleConf.java
index 4912fcc..ef5f05b 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleMfaAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleMfaAuthModuleConf.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib.auth;
 
-public class GoogleMfaAuthModuleConf extends AbstractAuthModuleConf {
+public class GoogleMfaAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -7883257599139312426L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JDBCAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JDBCAuthModuleConf.java
index 658a3c3..023ef1c 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JDBCAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JDBCAuthModuleConf.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.auth;
 import java.util.ArrayList;
 import java.util.List;
 
-public class JDBCAuthModuleConf extends AbstractAuthModuleConf {
+public class JDBCAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = 8383233437907219385L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JaasAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JaasAuthModuleConf.java
index 7291b8e..8768226 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JaasAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/JaasAuthModuleConf.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib.auth;
 
-public class JaasAuthModuleConf extends AbstractAuthModuleConf {
+public class JaasAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -7775771400318503131L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/LDAPAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/LDAPAuthModuleConf.java
index 97e4c26..6ab33eb 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/LDAPAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/LDAPAuthModuleConf.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.auth;
 import java.util.ArrayList;
 import java.util.List;
 
-public class LDAPAuthModuleConf extends AbstractAuthModuleConf {
+public class LDAPAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579422L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java
index cd6b008..5e5607a 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.auth;
 import java.util.HashMap;
 import java.util.Map;
 
-public class OIDCAuthModuleConf extends AbstractAuthModuleConf {
+public class OIDCAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579422L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/RadiusAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/RadiusAuthModuleConf.java
index 46f4eb2..4d94b15 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/RadiusAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/RadiusAuthModuleConf.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib.auth;
 
-public class RadiusAuthModuleConf extends AbstractAuthModuleConf {
+public class RadiusAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -2235771400318503131L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SAML2IdPAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SAML2IdPAuthModuleConf.java
index 0c4b0ed..f1489f9 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SAML2IdPAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SAML2IdPAuthModuleConf.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.common.lib.types.SAML2BindingType;
 
-public class SAML2IdPAuthModuleConf extends AbstractAuthModuleConf {
+public class SAML2IdPAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579422L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/StaticAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/StaticAuthModuleConf.java
index d73b347..f9c8a25 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/StaticAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/StaticAuthModuleConf.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.auth;
 import java.util.HashMap;
 import java.util.Map;
 
-public class StaticAuthModuleConf extends AbstractAuthModuleConf {
+public class StaticAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -7775771400318503131L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SyncopeAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SyncopeAuthModuleConf.java
index 0d0ecc4..f61834b 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SyncopeAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/SyncopeAuthModuleConf.java
@@ -20,7 +20,7 @@ package org.apache.syncope.common.lib.auth;
 
 import org.apache.syncope.common.lib.SyncopeConstants;
 
-public class SyncopeAuthModuleConf extends AbstractAuthModuleConf {
+public class SyncopeAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -3334329948161152222L;
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/U2FAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/U2FAuthModuleConf.java
index e7a84c0..b355ac3 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/U2FAuthModuleConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/U2FAuthModuleConf.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.common.lib.auth;
 
-public class U2FAuthModuleConf extends AbstractAuthModuleConf {
+public class U2FAuthModuleConf implements AuthModuleConf {
 
     private static final long serialVersionUID = -1235771400318503131L;
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyTO.java
index fc303d0..9c7bffe 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/PolicyTO.java
@@ -34,7 +34,7 @@ import org.apache.syncope.common.lib.to.EntityTO;
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "_class")
 @JsonPropertyOrder(value = { "_class", "key", "description" })
 @Schema(
-        subTypes = { AccountPolicyTO.class, PasswordPolicyTO.class, PullPolicyTO.class },
+        subTypes = { AccountPolicyTO.class, PasswordPolicyTO.class, ProvisioningPolicyTO.class },
         discriminatorProperty = "_class")
 public abstract class PolicyTO implements EntityTO {
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/ProvisioningPolicyTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/ProvisioningPolicyTO.java
index 548a402..5dd0122 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/ProvisioningPolicyTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/policy/ProvisioningPolicyTO.java
@@ -18,13 +18,17 @@
  */
 package org.apache.syncope.common.lib.policy;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
 
-@Schema(allOf = { PolicyTO.class })
+@Schema(allOf = { PolicyTO.class },
+        subTypes = { PullPolicyTO.class, PushPolicyTO.class },
+        discriminatorProperty = "_class")
 public abstract class ProvisioningPolicyTO extends PolicyTO {
 
     private static final long serialVersionUID = -3786048942148269602L;
@@ -33,6 +37,14 @@ public abstract class ProvisioningPolicyTO extends PolicyTO {
 
     private final Map<String, String> correlationRules = new HashMap<>();
 
+    @JacksonXmlProperty(localName = "_class", isAttribute = true)
+    @JsonProperty("_class")
+    @Schema(name = "_class", required = true, example = "org.apache.syncope.common.lib.policy.ProvisioningPolicyTO")
+    @Override
+    public String getDiscriminator() {
+        return getClass().getName();
+    }
+
     public ConflictResolutionAction getConflictResolutionAction() {
         return Optional.ofNullable(conflictResolutionAction).orElse(ConflictResolutionAction.IGNORE);
     }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java
index 2080c87..ec9cb05 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AccessTokenTO.java
@@ -57,8 +57,8 @@ public class AccessTokenTO implements EntityTO {
         return Optional.ofNullable(expirationTime).map(time -> new Date(time.getTime())).orElse(null);
     }
 
-    public void setExpirationTime(final Date expiryTime) {
-        this.expirationTime = Optional.ofNullable(expiryTime).map(time -> new Date(time.getTime())).orElse(null);
+    public void setExpirationTime(final Date expirationTime) {
+        this.expirationTime = Optional.ofNullable(expirationTime).map(time -> new Date(time.getTime())).orElse(null);
     }
 
     public String getOwner() {
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java
index fbe3852..f582cc9 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAccessTokenDAO.java
@@ -78,15 +78,15 @@ public class JPAAccessTokenDAO extends AbstractDAO<AccessToken> implements Acces
     private static String toOrderByStatement(final List<OrderByClause> orderByClauses) {
         StringBuilder statement = new StringBuilder();
 
-        for (OrderByClause clause : orderByClauses) {
+        orderByClauses.forEach(clause -> {
             String field = clause.getField().trim();
             if (ReflectionUtils.findField(JPAAccessToken.class, field) != null) {
                 statement.append("e.").append(field).append(' ').append(clause.getDirection().name());
             }
-        }
+        });
 
         if (statement.length() == 0) {
-            statement.append("ORDER BY e.expiryTime DESC");
+            statement.append(" ORDER BY e.expirationTime DESC");
         } else {
             statement.insert(0, "ORDER BY ");
         }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
index 8c51591..d624ffd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
@@ -314,13 +314,15 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
             if (!(policy instanceof AuthPolicy)
                     && !(policy instanceof AccessPolicy)
                     && !(policy instanceof AttrReleasePolicy)) {
-                for (ExternalResource resource : resourceDAO.findByPolicy(policy)) {
-                    policyTO.getUsedByResources().add(resource.getKey());
-                }
-            }
-            for (Realm realm : realmDAO.findByPolicy(policy)) {
-                policyTO.getUsedByRealms().add(realm.getFullPath());
+
+                policyTO.getUsedByResources().addAll(
+                        resourceDAO.findByPolicy(policy).stream().
+                                map(ExternalResource::getKey).collect(Collectors.toList()));
             }
+
+            policyTO.getUsedByRealms().addAll(
+                    realmDAO.findByPolicy(policy).stream().
+                            map(Realm::getFullPath).collect(Collectors.toList()));
         }
 
         return policyTO;
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java
index d2faf7f..4bc8775 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java
@@ -42,8 +42,8 @@ public class JWTAuthenticationProvider implements AuthenticationProvider {
         JWTClaimsSet claims = jwtAuthentication.getClaims();
         long referenceTime = System.currentTimeMillis();
 
-        Date expiryTime = claims.getExpirationTime();
-        if (expiryTime != null && expiryTime.getTime() < referenceTime) {
+        Date expirationTime = claims.getExpirationTime();
+        if (expirationTime != null && expirationTime.getTime() < referenceTime) {
             dataAccessor.removeExpired(claims.getJWTID());
             throw new CredentialsExpiredException("JWT is expired");
         }
diff --git a/docker/sra/src/main/resources/application.properties b/docker/sra/src/main/resources/application.properties
index b6b5147..22a059e 100644
--- a/docker/sra/src/main/resources/application.properties
+++ b/docker/sra/src/main/resources/application.properties
@@ -21,8 +21,11 @@ spring.main.banner-mode=log
 server.port=8080
 
 spring.cloud.gateway.metrics.enabled=true
+ 
+management.security.enabled=true
+management.endpoint.gateway.enabled=true
+management.endpoints.web.exposure.include=health,loggers,metrics,prometheus,gateway
+management.endpoint.health.show-details=always
 management.endpoint.metrics.enabled=true
-management.endpoint.prometheus.enabled=true
-management.metrics.export.prometheus.enabled=true
 
 service.discovery.address=${SERVICE_DISCOVERY_ADDRESS}
diff --git a/docker/wa/pom.xml b/docker/wa/pom.xml
index d7531e2..faeb8bc 100644
--- a/docker/wa/pom.xml
+++ b/docker/wa/pom.xml
@@ -140,6 +140,13 @@ under the License.
         <directory>src/main/resources</directory>
         <filtering>true</filtering>
       </resource>
+      <resource>
+        <directory>${basedir}/../../wa/starter/src/main/resources</directory>
+        <filtering>true</filtering>
+        <includes>
+          <include>wa.properties</include>
+        </includes>
+      </resource>
     </resources>
   </build>
 
diff --git a/docker/wa/src/main/resources/application.properties b/docker/wa/src/main/resources/application.properties
index 28404d9..b0d2e59 100644
--- a/docker/wa/src/main/resources/application.properties
+++ b/docker/wa/src/main/resources/application.properties
@@ -26,15 +26,15 @@ server.servlet.encoding.force=true
 
 server.servlet.contextPath=/syncope-wa
 
-spring.web.resources.static-locations=classpath:/thymeleaf/static,classpath:/syncope/static,classpath:/static
+server.servlet.session.timeout=300
+server.servlet.session.cookie.http-only=true
+server.servlet.session.tracking-modes=COOKIE
 
-management.endpoints.web.exposure.include=health,loggers,refresh,registeredServices
-management.endpoint.health.show-details=always
+spring.web.resources.static-locations=classpath:/thymeleaf/static,classpath:/syncope/static,classpath:/static
 
-management.endpoint.health.enabled=true
-management.endpoint.loggers.enabled=true
-management.endpoint.refresh.enabled=true
-management.endpoint.registeredServices.enabled=true
+cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
+management.endpoints.enabled-by-default=true
+management.endpoints.web.exposure.include=*
 
 # Cache service definitions for 5 minutes
 cas.service-registry.cache.duration=PT5M
@@ -43,6 +43,8 @@ cas.service-registry.cache.duration=PT5M
 cas.service-registry.schedule.repeat-interval=PT5M
 cas.service-registry.schedule.start-delay=PT30S
 
+cas.events.core.enabled=false
+
 ##
 # Allow configuration classes to override bean definitions from Spring Boot
 #
@@ -50,3 +52,5 @@ spring.main.allow-bean-definition-overriding=true
 spring.main.lazy-initialization=false
 
 service.discovery.address=${SERVICE_DISCOVERY_ADDRESS}
+
+version=${syncope.version}
diff --git a/docker/wa/src/main/resources/wa.properties b/docker/wa/src/main/resources/wa.properties
deleted file mode 100644
index 4665cc3..0000000
--- a/docker/wa/src/main/resources/wa.properties
+++ /dev/null
@@ -1,69 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-anonymousUser=${anonymousUser}
-anonymousKey=${anonymousKey}
-
-useGZIPCompression=true
-
-# Conf directories
-conf.directory=${conf.directory}
-cas.standalone.configurationDirectory=${conf.directory}
-
-cas.server.name=http://localhost:8080
-cas.server.prefix=${cas.server.name}/syncope-wa
-cas.server.scope=syncope.org
-
-cas.tgc.secure=false
-cas.logout.follow-service-redirects=true
-
-cas.authn.saml-idp.core.entity-id=${cas.server.name}/syncope-wa/saml
-cas.authn.saml-idp.metadata.http.metadata-backup-location=file:${conf.directory}/saml
-
-cas.authn.oidc.core.issuer=${cas.server.name}/syncope-wa/oidc/
-cas.authn.oidc.discovery.id-token-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
-cas.authn.oidc.discovery.user-info-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
-cas.authn.oauth.user-profile-view-type=FLAT
-
-# Disable access to the login endpoint
-# if no target application is specified.
-cas.sso.allow-missing-service-parameter=true
-
-# Disable the acceptable usage policy
-# by default for now.
-cas.acceptable-usage-policy.core.enabled=false
-
-management.endpoints.web.exposure.include=health,loggers,refresh
-management.endpoint.health.show-details=always
-
-management.endpoint.health.enabled=true
-management.endpoint.loggers.enabled=true
-management.endpoint.refresh.enabled=true
-
-cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
-
-spring.security.user.name=${anonymousUser}
-spring.security.user.password=${anonymousKey}
-
-springdoc.show-actuator=true
-springdoc.model-and-view-allowed=true
-springdoc.writer-with-default-pretty-printer=true
-springdoc.swagger-ui.displayRequestDuration=true
-
-cas.authn.mfa.web-authn.allowed-origins=http://localhost:8080
-cas.authn.mfa.web-authn.application-id=https://localhost:8443
-cas.authn.mfa.web-authn.relying-party-name=Syncope 
-cas.authn.mfa.web-authn.relying-party-id=syncope.apache.org
diff --git a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/OIDCProviderMappingPanel.java b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/OIDCProviderMappingPanel.java
index 2a5116c..b3c211b 100644
--- a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/OIDCProviderMappingPanel.java
+++ b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/OIDCProviderMappingPanel.java
@@ -25,7 +25,6 @@ import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -46,8 +45,7 @@ public class OIDCProviderMappingPanel extends AbstractMappingPanel {
         super(id,
                 mapItemTransformers,
                 jexlTransformers,
-                new ListModel<ItemTO>(opTO.getItems()),
-                true,
+                new ListModel<>(opTO.getItems()),
                 true,
                 MappingPurpose.NONE);
 
@@ -55,9 +53,14 @@ public class OIDCProviderMappingPanel extends AbstractMappingPanel {
     }
 
     @Override
+    protected boolean hidePurpose() {
+        return true;
+    }
+
+    @Override
     protected void onBeforeRender() {
         super.onBeforeRender();
-        purposeLabel.setVisible(false);
+        intAttrNameInfo.setVisible(false);
     }
 
     @Override
diff --git a/ext/saml2sp4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/SAML2IdPMappingPanel.java b/ext/saml2sp4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/SAML2IdPMappingPanel.java
index 1b9fba8..efde633 100644
--- a/ext/saml2sp4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/SAML2IdPMappingPanel.java
+++ b/ext/saml2sp4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/mapping/SAML2IdPMappingPanel.java
@@ -25,7 +25,6 @@ import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.to.SAML2SP4UIIdPTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -46,8 +45,7 @@ public class SAML2IdPMappingPanel extends AbstractMappingPanel {
         super(id,
                 mapItemTransformers,
                 jexlTransformers,
-                new ListModel<ItemTO>(idpTO.getItems()),
-                true,
+                new ListModel<>(idpTO.getItems()),
                 true,
                 MappingPurpose.NONE);
 
@@ -55,9 +53,14 @@ public class SAML2IdPMappingPanel extends AbstractMappingPanel {
     }
 
     @Override
+    protected boolean hidePurpose() {
+        return true;
+    }
+
+    @Override
     protected void onBeforeRender() {
         super.onBeforeRender();
-        purposeLabel.setVisible(false);
+        intAttrNameInfo.setVisible(false);
     }
 
     @Override
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 9a77694..cd4dc0b 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -97,12 +97,6 @@ under the License.
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.syncope.client.idm</groupId>
-      <artifactId>syncope-client-idm-lib</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.apache.syncope.ext.self-keymaster</groupId>
       <artifactId>syncope-ext-self-keymaster-client</artifactId>
       <version>${project.version}</version>
@@ -110,7 +104,7 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.syncope.client.am</groupId>
-      <artifactId>syncope-client-am-lib</artifactId>
+      <artifactId>syncope-client-am-console</artifactId>
       <version>${project.version}</version>
       <scope>test</scope>
     </dependency>
@@ -119,16 +113,6 @@ under the License.
       <artifactId>syncope-client-idm-console</artifactId>
       <version>${project.version}</version>
       <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>cglib</groupId>
-          <artifactId>cglib</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.ow2.asm</groupId>
-          <artifactId>asm-util</artifactId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.syncope.client.idrepo</groupId>
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
index 8615b3b..8e7c2c6 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractConsoleITCase.java
@@ -25,8 +25,11 @@ import com.giffing.wicket.spring.boot.starter.configuration.extensions.core.sett
 import com.giffing.wicket.spring.boot.starter.configuration.extensions.external.spring.boot.actuator.WicketEndpointRepositoryDefault;
 import java.util.List;
 import java.util.Locale;
+import org.apache.syncope.client.console.SyncopeAMConsoleContext;
 import org.apache.syncope.client.console.SyncopeIdMConsoleContext;
 import org.apache.syncope.client.console.SyncopeWebApplication;
+import org.apache.syncope.client.console.commons.IdRepoPolicyTabProvider;
+import org.apache.syncope.client.console.commons.PolicyTabProvider;
 import org.apache.syncope.client.console.commons.PreviewUtils;
 import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
 import org.apache.syncope.client.console.init.MIMETypesLoader;
@@ -100,6 +103,11 @@ public abstract class AbstractConsoleITCase extends AbstractUITCase {
         public UserFormFinalizerUtils userFormFinalizerUtils() {
             return new UserFormFinalizerUtils();
         }
+
+        @Bean
+        public PolicyTabProvider idRepoPolicyTabProvider() {
+            return new IdRepoPolicyTabProvider();
+        }
     }
 
     @BeforeAll
@@ -109,6 +117,7 @@ public abstract class AbstractConsoleITCase extends AbstractUITCase {
         AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
         ctx.register(SyncopeConsoleWebApplicationTestConfig.class);
         ctx.register(SyncopeWebApplication.class);
+        ctx.register(SyncopeAMConsoleContext.class);
         ctx.register(SyncopeIdMConsoleContext.class);
         ctx.refresh();
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java
index 782bba8..f206261 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/PoliciesITCase.java
@@ -41,11 +41,10 @@ public class PoliciesITCase extends AbstractConsoleITCase {
         TESTER.assertRenderedPage(Policies.class);
     }
 
-    private static void createAccountPolicy(final String description) {
+    private static void createAccountPolicy(String description) {
         TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:0:link");
         TESTER.clickLink("body:content:tabbedPanel:panel:container:content:add");
-        TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer",
-                Modal.class);
+        TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer", Modal.class);
 
         Component modal = TESTER.getComponentFromLastRenderedPage(
                 "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer");
@@ -99,11 +98,10 @@ public class PoliciesITCase extends AbstractConsoleITCase {
         assertNotNull(component);
     }
 
-    private static void createPasswordPolicy(final String description) {
+    private static void createPasswordPolicy(String description) {
         TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:1:link");
         TESTER.clickLink("body:content:tabbedPanel:panel:container:content:add");
-        TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer",
-                Modal.class);
+        TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer", Modal.class);
 
         Component modal = TESTER.getComponentFromLastRenderedPage(
                 "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer");
@@ -150,11 +148,10 @@ public class PoliciesITCase extends AbstractConsoleITCase {
                 + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", description));
     }
 
-    private static void createPullPolicy(final String description) {
-        TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:2:link");
+    private static void createPullPolicy(String description) {
+        TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:5:link");
         TESTER.clickLink("body:content:tabbedPanel:panel:container:content:add");
-        TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer",
-                Modal.class);
+        TESTER.assertComponent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer", Modal.class);
 
         Component modal = TESTER.getComponentFromLastRenderedPage(
                 "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer");
@@ -196,7 +193,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
                 + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", description));
     }
 
-    private static void deleteAccountPolicy(final String description) {
+    private static void deleteAccountPolicy(String description) {
         TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:0:link");
         Component component = findComponentByProp("description",
                 "body:content:tabbedPanel:panel:container:content:"
@@ -221,7 +218,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
                 + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", description));
     }
 
-    private static void deletePasswordPolicy(final String description) {
+    private static void deletePasswordPolicy(String description) {
         TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:1:link");
         Component component = findComponentByProp("description",
                 "body:content:tabbedPanel:panel:container:content:"
@@ -246,8 +243,8 @@ public class PoliciesITCase extends AbstractConsoleITCase {
                 + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", description));
     }
 
-    private static void deletePullPolicy(final String description) {
-        TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:2:link");
+    private static void deletePullPolicy(String description) {
+        TESTER.clickLink("body:content:tabbedPanel:tabs-container:tabs:5:link");
         Component component = findComponentByProp("description",
                 "body:content:tabbedPanel:panel:container:content:"
                 + "searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", description);
@@ -279,14 +276,14 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createDeleteAccountPolicy() {
-        final String description = "My Test Account Policy";
+        String description = "My Test Account Policy";
         createAccountPolicy(description);
         deleteAccountPolicy(description);
     }
 
     @Test
     public void cloneDeleteAccountPolicy() {
-        final String description = "My Test Account Policy to be cloned";
+        String description = "My Test Account Policy to be cloned";
         createAccountPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -330,14 +327,14 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createDeletePasswordPolicy() {
-        final String description = "My Test Password Policy";
+        String description = "My Test Password Policy";
         createPasswordPolicy(description);
         deletePasswordPolicy(description);
     }
 
     @Test
     public void cloneDeletePasswordPolicy() {
-        final String description = "My Test Password Policy to be cloned";
+        String description = "My Test Password Policy to be cloned";
         createPasswordPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -381,14 +378,14 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createDeletePullPolicy() {
-        final String description = "My Test Pull Policy";
+        String description = "My Test Pull Policy";
         createPullPolicy(description);
         deletePullPolicy(description);
     }
 
     @Test
     public void cloneDeletePullPolicy() {
-        final String description = "My Test Pull Policy to be cloned";
+        String description = "My Test Pull Policy to be cloned";
         createPullPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -432,7 +429,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createUpdateDeleteAccountPolicy() {
-        final String description = "Account Policy To Be Updated";
+        String description = "Account Policy To Be Updated";
         createAccountPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -526,7 +523,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createComposeDeleteAccountPolicy() {
-        final String description = "Account Policy To Be Composed";
+        String description = "Account Policy To Be Composed";
         createAccountPolicy(description);
         composeDefaultAccountPolicy(description);
         deleteAccountPolicy(description);
@@ -534,7 +531,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createUpdateDeletePasswordPolicy() {
-        final String description = "Password Policy To Be Updated";
+        String description = "Password Policy To Be Updated";
         createPasswordPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -589,7 +586,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createComposeDeletePasswordPolicy() {
-        final String description = "Password Policy To Be Composed";
+        String description = "Password Policy To Be Composed";
         createPasswordPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -634,7 +631,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createUpdateDeletePullPolicy() {
-        final String description = "Pull Policy To Be Updated";
+        String description = "Pull Policy To Be Updated";
         createPullPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -689,7 +686,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void createComposeDeletePullPolicy() {
-        final String description = "Pull Policy To Be Composed";
+        String description = "Pull Policy To Be Composed";
         createPullPolicy(description);
 
         Component component = findComponentByProp("description",
@@ -738,7 +735,7 @@ public class PoliciesITCase extends AbstractConsoleITCase {
 
     @Test
     public void issueSYNCOPE1030() {
-        final String description = "SYNCOPE-1030";
+        String description = "SYNCOPE-1030";
         // Create account policy
         createAccountPolicy(description);
         composeDefaultAccountPolicy(description);
@@ -753,13 +750,12 @@ public class PoliciesITCase extends AbstractConsoleITCase {
         TESTER.assertComponent("body:content:body:outerObjectsRepeater:0:outer", Modal.class);
 
         // set new account policy
-        TESTER.assertLabel(
-                "body:content:body:outerObjectsRepeater:0:outer:form:content:form:view:details:container:"
-                + "accountPolicy:field-label", "Account Policy");
+        TESTER.assertLabel("body:content:body:outerObjectsRepeater:0:outer:form:content:form:view:details:container:"
+                + "policies:1:field-label", "Account Policy");
 
         FormTester formTester = TESTER.newFormTester(
                 "body:content:body:outerObjectsRepeater:0:outer:form:content:form");
-        formTester.select("view:details:container:accountPolicy:dropDownChoiceField", 0);
+        formTester.select("view:details:container:policies:1:dropDownChoiceField", 0);
         formTester.submit("buttons:finish");
 
         assertSuccessMessage();
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
index fb2e3e1..8b4df01 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java
@@ -41,7 +41,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
     @Test
     public void read() {
         TESTER.assertLabel(
-                "body:content:body:container:content:tabbedPanel:panel:container:accountPolicy:field-label",
+                "body:content:body:container:content:tabbedPanel:panel:container:policies:1:field-label",
                 "Account Policy");
     }
 
@@ -83,7 +83,7 @@ public class RealmsITCase extends AbstractConsoleITCase {
         TESTER.cleanupFeedbackMessages();
 
         TESTER.assertLabel(
-                "body:content:body:container:content:tabbedPanel:panel:container:accountPolicy:field-label",
+                "body:content:body:container:content:tabbedPanel:panel:container:policies:1:field-label",
                 "Account Policy");
 
         TESTER.assertLabel("body:content:realmChoicePanel:container:realm", "/");
diff --git a/fit/wa-reference/src/main/resources/wa.properties b/fit/wa-reference/src/main/resources/wa.properties
index 82fc156..4cf189c 100644
--- a/fit/wa-reference/src/main/resources/wa.properties
+++ b/fit/wa-reference/src/main/resources/wa.properties
@@ -21,22 +21,22 @@ useGZIPCompression=true
 
 # Conf directories
 conf.directory=${conf.directory}
-cas.standalone.configurationDirectory=${conf.directory}
+cas.standalone.configuration-directory=${conf.directory}
 
 cas.server.name=http://localhost:9080
 cas.server.prefix=${cas.server.name}/syncope-wa
 cas.server.scope=syncope.org
-cas.authn.syncope.url=http://localhost:9080/syncope/rest/
 
 cas.tgc.secure=false
 cas.logout.follow-service-redirects=true
 
-cas.authn.saml-idp.core.entity-id=http://localhost:9080/saml
+cas.authn.saml-idp.core.entity-id=${cas.server.name}/syncope-wa/saml
 cas.authn.saml-idp.metadata.http.metadata-backup-location=file:${conf.directory}/saml
 
-cas.authn.oidc.core.issuer=http://localhost:9080/syncope-wa/oidc/
+cas.authn.oidc.core.issuer=${cas.server.name}/syncope-wa/oidc/
 cas.authn.oidc.discovery.id-token-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
 cas.authn.oidc.discovery.user-info-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
+cas.authn.oauth.user-profile-view-type=FLAT
 
 # Disable access to the login endpoint
 # if no target application is specified.
@@ -46,15 +46,6 @@ cas.sso.allow-missing-service-parameter=true
 # by default for now.
 cas.acceptable-usage-policy.core.enabled=false
 
-management.endpoints.web.exposure.include=health,loggers,refresh
-management.endpoint.health.show-details=always
-
-management.endpoint.health.enabled=true
-management.endpoint.loggers.enabled=true
-management.endpoint.refresh.enabled=true
-
-cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
-
 spring.security.user.name=${anonymousUser}
 spring.security.user.password=${anonymousKey}
 
@@ -63,7 +54,9 @@ springdoc.model-and-view-allowed=true
 springdoc.writer-with-default-pretty-printer=true
 springdoc.swagger-ui.displayRequestDuration=true
 
-cas.authn.mfa.web-authn.allowed-origins=http://localhost:9080
-cas.authn.mfa.web-authn.application-id=https://localhost:9090
+cas.authn.mfa.web-authn.allowed-origins=${cas.server.name}
+cas.authn.mfa.web-authn.application-id=https://localhost:8443
 cas.authn.mfa.web-authn.relying-party-name=Syncope 
 cas.authn.mfa.web-authn.relying-party-id=syncope.apache.org
+
+cas.authn.syncope.url=${cas.server.name}/syncope/rest/
diff --git a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
index 068afa0..803f0f5 100644
--- a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
+++ b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
@@ -168,7 +168,8 @@ public class SAML2SP4UIITCase extends AbstractUIITCase {
         assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
 
         // 2. click on the SAML 2.0 IdP
-        get = new HttpGet(baseURL + SAML2SP4UIConstants.URL_CONTEXT + "/login?idp=http%3A//localhost%3A9080/saml");
+        get = new HttpGet(baseURL + SAML2SP4UIConstants.URL_CONTEXT 
+                + "/login?idp=http%3A//localhost%3A9080/syncope-wa/saml");
         response = httpclient.execute(get, context);
 
         // 2a. post SAML request
diff --git a/pom.xml b/pom.xml
index fbe18eb..8e46fc5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -474,6 +474,7 @@ under the License.
     <chartjs.version>1.0.2</chartjs.version>
 
     <wicket.version>9.2.0</wicket.version>
+    <wicketstuff.version>9.2.0</wicketstuff.version>
     <wicket-jqueryui.version>9.2.1</wicket-jqueryui.version>
     <wicket-bootstrap.version>5.0.3</wicket-bootstrap.version>
     <wicket-spring-boot.version>3.0.4</wicket-spring-boot.version>
@@ -1759,6 +1760,11 @@ under the License.
         <version>${wicket.version}</version>
       </dependency>
       <dependency>
+        <groupId>org.wicketstuff</groupId>
+        <artifactId>wicketstuff-editable-grid</artifactId>
+        <version>${wicketstuff.version}</version>
+      </dependency>
+      <dependency>
         <groupId>com.googlecode.wicket-jquery-ui</groupId>
         <artifactId>wicket-jquery-ui</artifactId>
         <version>${wicket-jqueryui.version}</version>
diff --git a/wa/starter/src/main/resources/application.properties b/wa/starter/src/main/resources/application.properties
index a2d254d..844b6e3 100644
--- a/wa/starter/src/main/resources/application.properties
+++ b/wa/starter/src/main/resources/application.properties
@@ -32,13 +32,9 @@ server.servlet.session.tracking-modes=COOKIE
 
 spring.web.resources.static-locations=classpath:/thymeleaf/static,classpath:/syncope/static,classpath:/static
 
-management.endpoints.web.exposure.include=health,loggers,refresh,registeredServices
-management.endpoint.health.show-details=always
-
-management.endpoint.health.enabled=true
-management.endpoint.loggers.enabled=true
-management.endpoint.refresh.enabled=true
-management.endpoint.registeredServices.enabled=true
+cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
+management.endpoints.enabled-by-default=true
+management.endpoints.web.exposure.include=*
 
 # Cache service definitions for 5 minutes
 cas.service-registry.cache.duration=PT5M
diff --git a/wa/starter/src/main/resources/wa.properties b/wa/starter/src/main/resources/wa.properties
index 77cfcb4..738f9c2 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -46,15 +46,6 @@ cas.sso.allow-missing-service-parameter=true
 # by default for now.
 cas.acceptable-usage-policy.core.enabled=false
 
-management.endpoints.web.exposure.include=health,loggers,refresh
-management.endpoint.health.show-details=always
-
-management.endpoint.health.enabled=true
-management.endpoint.loggers.enabled=true
-management.endpoint.refresh.enabled=true
-
-cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
-
 spring.security.user.name=${anonymousUser}
 spring.security.user.password=${anonymousKey}
 
@@ -63,7 +54,9 @@ springdoc.model-and-view-allowed=true
 springdoc.writer-with-default-pretty-printer=true
 springdoc.swagger-ui.displayRequestDuration=true
 
-cas.authn.mfa.web-authn.allowed-origins=http://localhost:8080
+cas.authn.mfa.web-authn.allowed-origins=${cas.server.name}
 cas.authn.mfa.web-authn.application-id=https://localhost:8443
 cas.authn.mfa.web-authn.relying-party-name=Syncope 
 cas.authn.mfa.web-authn.relying-party-id=syncope.apache.org
+
+cas.authn.syncope.url=${cas.server.name}/syncope/rest/
diff --git a/wa/starter/src/test/resources/debug/application-debug.properties b/wa/starter/src/test/resources/debug/application-debug.properties
index 8a2c08a..fffeac6 100644
--- a/wa/starter/src/test/resources/debug/application-debug.properties
+++ b/wa/starter/src/test/resources/debug/application-debug.properties
@@ -15,3 +15,5 @@
 # specific language governing permissions and limitations
 # under the License.
 #debug=true
+
+cas.authn.syncope.url=http://localhost:9081/syncope/rest/
diff --git a/wa/starter/src/test/resources/debug/wa.properties b/wa/starter/src/test/resources/debug/wa.properties
deleted file mode 100644
index 3814f6a..0000000
--- a/wa/starter/src/test/resources/debug/wa.properties
+++ /dev/null
@@ -1,70 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-anonymousUser=${anonymousUser}
-anonymousKey=${anonymousKey}
-
-useGZIPCompression=true
-
-# Conf directories
-conf.directory=${conf.directory}
-cas.standalone.configurationDirectory=${conf.directory}
-
-cas.server.name=http://localhost:8080
-cas.server.prefix=${cas.server.name}/syncope-wa
-cas.server.scope=syncope.org
-cas.authn.syncope.url=http://localhost:9081/syncope/rest/
-
-cas.tgc.secure=false
-cas.logout.follow-service-redirects=true
-
-cas.authn.saml-idp.core.entity-id=${cas.server.name}/syncope-wa/saml
-cas.authn.saml-idp.metadata.http.metadata-backup-location=file:${conf.directory}/saml
-
-cas.authn.oidc.core.issuer=${cas.server.name}/syncope-wa/oidc/
-cas.authn.oidc.discovery.id-token-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
-cas.authn.oidc.discovery.user-info-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
-cas.authn.oauth.user-profile-view-type=FLAT
-
-# Disable access to the login endpoint
-# if no target application is specified.
-cas.sso.allow-missing-service-parameter=true
-
-# Disable the acceptable usage policy
-# by default for now.
-cas.acceptable-usage-policy.core.enabled=false
-
-management.endpoints.web.exposure.include=health,loggers,refresh
-management.endpoint.health.show-details=always
-
-management.endpoint.health.enabled=true
-management.endpoint.loggers.enabled=true
-management.endpoint.refresh.enabled=true
-
-cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
-
-spring.security.user.name=${anonymousUser}
-spring.security.user.password=${anonymousKey}
-
-springdoc.show-actuator=true
-springdoc.model-and-view-allowed=true
-springdoc.writer-with-default-pretty-printer=true
-springdoc.swagger-ui.displayRequestDuration=true
-
-cas.authn.mfa.web-authn.allowed-origins=http://localhost:8080
-cas.authn.mfa.web-authn.application-id=https://localhost:8443
-cas.authn.mfa.web-authn.relying-party-name=Syncope 
-cas.authn.mfa.web-authn.relying-party-id=syncope.apache.org