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 2020/05/06 11:44:39 UTC

[syncope] branch master updated: [SYNCOPE-1557] Allowing for flexible Auth, Access, AttrRelease and ClientApp translation (#184)

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 3b0534b  [SYNCOPE-1557] Allowing for flexible Auth, Access, AttrRelease and ClientApp translation (#184)
3b0534b is described below

commit 3b0534be055fd528738b2dd81e8896c717de9b47
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Wed May 6 13:44:28 2020 +0200

    [SYNCOPE-1557] Allowing for flexible Auth, Access, AttrRelease and ClientApp translation (#184)
---
 .../lib/policy/AbstractAccessPolicyConf.java       |  13 +-
 .../lib/policy/AbstractAuthPolicyCriteriaConf.java |   1 -
 .../common/lib/policy/AccessPolicyConf.java        |   2 +-
 .../common/lib/{to => policy}/AccessPolicyTO.java  |  16 +-
 .../lib/policy/AllowedAttrReleasePolicyConf.java   |  15 +-
 .../lib/{to => policy}/AttrReleasePolicyTO.java    |  16 +-
 .../common/lib/policy/AuthPolicyCriteriaConf.java  |   1 -
 .../common/lib/{to => policy}/AuthPolicyTO.java    |  17 +-
 .../common/lib/policy/DefaultAccessPolicyConf.java |   3 +-
 .../common/lib/policy/DefaultAuthPolicyConf.java   |   2 +-
 .../lib/policy/DefaultAuthPolicyCriteriaConf.java  |   2 +-
 .../common/lib/types/AMImplementationType.java     |  44 -----
 .../apache/syncope/common/lib/wa/WAClientApp.java  |   1 -
 .../init/ClassPathScanImplementationLookup.java    | 127 -------------
 .../core/persistence/api/dao/PolicyDAO.java        |  10 -
 .../api/entity/policy/AccessPolicy.java            |  11 +-
 .../api/entity/policy/AttrReleasePolicy.java       |  10 +-
 .../persistence/api/entity/policy/AuthPolicy.java  |  12 +-
 .../src/test/resources/domains/MasterContent.xml   |  28 ++-
 .../core/persistence/jpa/dao/JPAPolicyDAO.java     |  27 ---
 .../jpa/entity/policy/JPAAccessPolicy.java         |  45 ++---
 .../jpa/entity/policy/JPAAttrReleasePolicy.java    |  45 ++---
 .../jpa/entity/policy/JPAAuthPolicy.java           |  43 ++---
 .../jpa/entity/policy/JPAPolicyUtilsFactory.java   |  10 +-
 .../jpa/inner/AbstractClientAppTest.java           |  49 +----
 .../persistence/jpa/inner/ImplementationTest.java  |   9 +-
 .../core/persistence/jpa/inner/PolicyTest.java     |  86 +++------
 .../src/test/resources/domains/MasterContent.xml   |  24 +--
 .../java/data/ImplementationDataBinderImpl.java    |  42 -----
 .../java/data/PolicyDataBinderImpl.java            |  50 ++---
 .../java/data/wa/WAClientAppBinderImpl.java        |  19 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |   4 +-
 .../apache/syncope/fit/core/ClientAppITCase.java   |   2 +-
 .../org/apache/syncope/fit/core/PolicyITCase.java  | 163 ++++------------
 .../org/apache/syncope/fit/core/RealmITCase.java   |  47 ++---
 .../bootstrap/SyncopeWABootstrapConfiguration.java |   1 -
 .../bootstrap/SyncopeWAPropertySourceLocator.java  |   1 -
 .../syncope/wa/{ => bootstrap}/WARestClient.java   |   2 +-
 .../wa/starter/RegisteredServiceMapper.java        | 205 ---------------------
 .../syncope/wa/starter/SyncopeServiceRegistry.java |  21 ++-
 .../wa/starter/SyncopeWAAuditTrailManager.java     |   2 +-
 .../syncope/wa/starter/SyncopeWAConfiguration.java | 106 +++++++++--
 .../wa/starter/SyncopeWARefreshContextJob.java     |   2 +-
 .../syncope/wa/starter/mapping/AccessMapFor.java   |  28 ++-
 .../syncope/wa/starter/mapping/AccessMapper.java   |  17 +-
 .../starter/mapping/AllowedAttrReleaseMapper.java  |  54 ++++++
 .../wa/starter/mapping/AttrReleaseMapFor.java      |  28 ++-
 .../wa/starter/mapping/AttrReleaseMapper.java      |  17 +-
 .../syncope/wa/starter/mapping/AuthMapFor.java     |  28 ++-
 .../syncope/wa/starter/mapping/AuthMapper.java     |  17 +-
 .../wa/starter/mapping/ClientAppMapFor.java        |  28 ++-
 .../wa/starter/mapping/ClientAppMapper.java        |  29 ++-
 .../wa/starter/mapping/DefaultAccessMapper.java    |  49 +++++
 .../wa/starter/mapping/DefaultAuthMapper.java      |  53 ++++++
 .../syncope/wa/starter/mapping/OIDCRPTOMapper.java |  86 +++++++++
 .../starter/mapping/RegisteredServiceMapper.java   | 131 +++++++++++++
 .../wa/starter/mapping/SAML2SPTOMapper.java        |  94 ++++++++++
 .../metadata/RestfulSamlIdPMetadataGenerator.java  |   4 +-
 .../metadata/RestfulSamlIdPMetadataLocator.java    |   4 +-
 59 files changed, 869 insertions(+), 1134 deletions(-)

diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccessPolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccessPolicyConf.java
index 653fe11..5152d95 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccessPolicyConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccessPolicyConf.java
@@ -43,7 +43,7 @@ public abstract class AbstractAccessPolicyConf implements Serializable, AccessPo
     private boolean ssoEnabled = true;
 
     @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
-    private final Map<String, Set<String>> requiredAttributes = new LinkedHashMap<>();
+    private final Map<String, Set<String>> requiredAttrs = new LinkedHashMap<>();
 
     public AbstractAccessPolicyConf() {
         setName(getClass().getName());
@@ -76,12 +76,11 @@ public abstract class AbstractAccessPolicyConf implements Serializable, AccessPo
         this.ssoEnabled = ssoEnabled;
     }
 
-    @XmlElementWrapper(name = "requiredAttributes")
-    @XmlElement(name = "requiredAttribute")
-    @JsonProperty("requiredAttributes")
+    @XmlElementWrapper(name = "requiredAttrs")
+    @XmlElement(name = "requiredAttr")
+    @JsonProperty("requiredAttrs")
     @Override
-    public Map<String, Set<String>> getRequiredAttributes() {
-        return requiredAttributes;
+    public Map<String, Set<String>> getRequiredAttrs() {
+        return requiredAttrs;
     }
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java
index 1f497de..a25438f 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java
@@ -46,5 +46,4 @@ public abstract class AbstractAuthPolicyCriteriaConf implements AuthPolicyCriter
     public final void setName(final String name) {
         this.name = name;
     }
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java
index 3cb0505..9587418 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java
@@ -37,5 +37,5 @@ public interface AccessPolicyConf extends Serializable {
 
     boolean isSsoEnabled();
 
-    Map<String, Set<String>> getRequiredAttributes();
+    Map<String, Set<String>> getRequiredAttrs();
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AccessPolicyTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyTO.java
similarity index 80%
rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AccessPolicyTO.java
rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyTO.java
index f134fb6..34c500d 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AccessPolicyTO.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyTO.java
@@ -17,11 +17,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.to;
+package org.apache.syncope.common.lib.policy;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import org.apache.syncope.common.lib.policy.PolicyTO;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
@@ -32,22 +31,21 @@ public class AccessPolicyTO extends PolicyTO {
 
     private static final long serialVersionUID = -6711411162433533300L;
 
-    private String configuration;
+    private AccessPolicyConf conf;
 
     @XmlTransient
     @JsonProperty("@class")
-    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.to.AccessPolicyTO")
+    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.policy.AccessPolicyTO")
     @Override
     public String getDiscriminator() {
         return getClass().getName();
     }
 
-    public String getConfiguration() {
-        return configuration;
+    public AccessPolicyConf getConf() {
+        return conf;
     }
 
-    public void setConfiguration(final String configuration) {
-        this.configuration = configuration;
+    public void setConf(final AccessPolicyConf conf) {
+        this.conf = conf;
     }
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AllowedAttrReleasePolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AllowedAttrReleasePolicyConf.java
index 3bcccd0..d0174ff 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AllowedAttrReleasePolicyConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AllowedAttrReleasePolicyConf.java
@@ -26,7 +26,7 @@ import java.util.List;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 
-@XmlRootElement(name = "AllowedAttrReleasePolicyConf")
+@XmlRootElement(name = "allowedAttrReleasePolicyConf")
 @XmlType
 public class AllowedAttrReleasePolicyConf extends AbstractAttrReleasePolicyConf implements AttrReleasePolicyConf {
 
@@ -36,13 +36,12 @@ public class AllowedAttrReleasePolicyConf extends AbstractAttrReleasePolicyConf
      * Specify the list of allowed attribute to release.
      * Use the special {@code *} to release everything.
      */
-    private final List<String> allowedAttributes = new ArrayList<>();
+    private final List<String> allowedAttrs = new ArrayList<>();
 
-    @XmlElementWrapper(name = "allowedAttributes")
-    @XmlElement(name = "allowedAttribute")
-    @JsonProperty("allowedAttributes")
-    public List<String> getAllowedAttributes() {
-        return allowedAttributes;
+    @XmlElementWrapper(name = "allowedAttrs")
+    @XmlElement(name = "allowedAttr")
+    @JsonProperty("allowedAttrs")
+    public List<String> getAllowedAttrs() {
+        return allowedAttrs;
     }
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AttrReleasePolicyTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AttrReleasePolicyTO.java
similarity index 80%
rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AttrReleasePolicyTO.java
rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AttrReleasePolicyTO.java
index a5ca384..1d7f050 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AttrReleasePolicyTO.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AttrReleasePolicyTO.java
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.to;
+package org.apache.syncope.common.lib.policy;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import org.apache.syncope.common.lib.policy.PolicyTO;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
@@ -31,22 +30,21 @@ public class AttrReleasePolicyTO extends PolicyTO {
 
     private static final long serialVersionUID = -1432411162433533300L;
 
-    private String configuration;
+    private AttrReleasePolicyConf conf;
 
     @XmlTransient
     @JsonProperty("@class")
-    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.to.AttrReleasePolicyTO")
+    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.policy.AttrReleasePolicyTO")
     @Override
     public String getDiscriminator() {
         return getClass().getName();
     }
 
-    public String getConfiguration() {
-        return configuration;
+    public AttrReleasePolicyConf getConf() {
+        return conf;
     }
 
-    public void setConfiguration(final String configuration) {
-        this.configuration = configuration;
+    public void setConf(final AttrReleasePolicyConf conf) {
+        this.conf = conf;
     }
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java
index 1847fc4..4ba54bb 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java
@@ -29,7 +29,6 @@ import java.io.Serializable;
  * or "any module can validate the user" before the policy can consider it
  * a success.
  */
-@FunctionalInterface
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
 public interface AuthPolicyCriteriaConf extends Serializable {
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AuthPolicyTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyTO.java
similarity index 76%
rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AuthPolicyTO.java
rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyTO.java
index e18cd93..8301d69 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AuthPolicyTO.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyTO.java
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.to;
+package org.apache.syncope.common.lib.policy;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import org.apache.syncope.common.lib.policy.PolicyTO;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
@@ -31,23 +30,21 @@ public class AuthPolicyTO extends PolicyTO {
 
     private static final long serialVersionUID = -6711411162433533300L;
 
-    private String configuration;
+    private AuthPolicyConf conf;
 
     @XmlTransient
     @JsonProperty("@class")
-    @Schema(name = "@class", required = true,
-            example = "org.apache.syncope.common.lib.to.AuthPolicyTO")
+    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.policy.AuthPolicyTO")
     @Override
     public String getDiscriminator() {
         return getClass().getName();
     }
 
-    public String getConfiguration() {
-        return configuration;
+    public AuthPolicyConf getConf() {
+        return conf;
     }
 
-    public void setConfiguration(final String configuration) {
-        this.configuration = configuration;
+    public void setConf(final AuthPolicyConf conf) {
+        this.conf = conf;
     }
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
index d12c98b..df2315c 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
@@ -21,10 +21,9 @@ package org.apache.syncope.common.lib.policy;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 
-@XmlRootElement(name = "DefaultAccessPolicyConf")
+@XmlRootElement(name = "defaultAccessPolicyConf")
 @XmlType
 public class DefaultAccessPolicyConf extends AbstractAccessPolicyConf implements AccessPolicyConf {
 
     private static final long serialVersionUID = -1969836600059025380L;
-
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyConf.java
index 3076d39..ce1507b 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyConf.java
@@ -26,7 +26,7 @@ import java.util.List;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 
-@XmlRootElement(name = "DefaultAuthPolicyConf")
+@XmlRootElement(name = "defaultAuthPolicyConf")
 @XmlType
 public class DefaultAuthPolicyConf extends AbstractAuthPolicyConf implements AuthPolicyConf {
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
index 8bcb84b..96b17ca 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.policy;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 
-@XmlRootElement(name = "AnyAuthPolicyCriteriaConf")
+@XmlRootElement(name = "defaultAuthPolicyCriteriaConf")
 @XmlType
 public class DefaultAuthPolicyCriteriaConf extends AbstractAuthPolicyCriteriaConf {
 
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMImplementationType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMImplementationType.java
deleted file mode 100644
index 1a6a7a0..0000000
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMImplementationType.java
+++ /dev/null
@@ -1,44 +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.
- */
-package org.apache.syncope.common.lib.types;
-
-import org.apache.commons.lang3.tuple.Pair;
-import java.util.Map;
-
-public final class AMImplementationType {
-
-    public static final String AUTH_POLICY_CONF = "AUTH_POLICY_CONF";
-
-    public static final String ACCESS_POLICY_CONF = "ACCESS_POLICY_CONF";
-
-    public static final String ATTR_RELEASE_POLICY_CONF = "ATTR_RELEASE_POLICY_CONF";
-
-    private AMImplementationType() {
-        // private constructor for static utility class
-    }
-
-    private static final Map<String, String> VALUES = Map.ofEntries(
-            Pair.of(AUTH_POLICY_CONF, "org.apache.syncope.common.lib.policy.AuthPolicyConf"),
-            Pair.of(ACCESS_POLICY_CONF, "org.apache.syncope.common.lib.policy.AccessPolicyConf"),
-            Pair.of(ATTR_RELEASE_POLICY_CONF, "org.apache.syncope.common.lib.policy.AttrReleasePolicyConf"));
-
-    public static Map<String, String> values() {
-        return VALUES;
-    }
-}
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/WAClientApp.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/WAClientApp.java
index 524ffc9..55771de 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/WAClientApp.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/wa/WAClientApp.java
@@ -67,5 +67,4 @@ public class WAClientApp implements Serializable {
     public void setAttrReleasePolicyConf(final AttrReleasePolicyConf attrReleasePolicyConf) {
         this.attrReleasePolicyConf = attrReleasePolicyConf;
     }
-
 }
diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
deleted file mode 100644
index 04f4463..0000000
--- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ /dev/null
@@ -1,127 +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.
- */
-package org.apache.syncope.core.logic.init;
-
-import java.lang.reflect.Modifier;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import org.apache.syncope.common.lib.policy.AccessPolicyConf;
-import org.apache.syncope.common.lib.types.AMImplementationType;
-import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
-import org.apache.syncope.core.persistence.api.ImplementationLookup;
-import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
-import org.springframework.core.Ordered;
-import org.springframework.core.type.filter.AssignableTypeFilter;
-import org.springframework.util.ClassUtils;
-import org.apache.syncope.common.lib.policy.AuthPolicyConf;
-
-/**
- * Cache class names for all implementations of Syncope interfaces found in classpath, for later usage.
- */
-public class ClassPathScanImplementationLookup implements SyncopeCoreLoader {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ImplementationLookup.class);
-
-    private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.core";
-
-    private Map<String, Set<String>> classNames;
-
-    private Map<Class<? extends AuthPolicyConf>, Class<? extends AuthPolicyConf>> authPolicyClasses;
-
-    private Map<Class<? extends AccessPolicyConf>, Class<? extends AccessPolicyConf>> accessPolicyClasses;
-
-    @Override
-    public int getOrder() {
-        return Ordered.HIGHEST_PRECEDENCE;
-    }
-
-    /**
-     * This method can be overridden by subclasses to customize classpath scan.
-     *
-     * @return basePackage for classpath scanning
-     */
-    protected static String getBasePackage() {
-        return DEFAULT_BASE_PACKAGE;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void load() {
-        classNames = new HashMap<>();
-        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
-        ImplementationTypesHolder.getInstance().getValues().forEach((typeName, typeInterface) -> {
-            classNames.put(typeName, new HashSet<>());
-            try {
-                scanner.addIncludeFilter(new AssignableTypeFilter(
-                        ClassUtils.resolveClassName(typeInterface, ClassUtils.getDefaultClassLoader())));
-            } catch (IllegalArgumentException e) {
-                LOG.error("Could not find class, ignoring...", e);
-            }
-        });
-
-        authPolicyClasses = new HashMap<>();
-        accessPolicyClasses = new HashMap<>();
-
-        scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
-            try {
-                Class<?> clazz = ClassUtils.resolveClassName(
-                        Objects.requireNonNull(bd.getBeanClassName()), ClassUtils.getDefaultClassLoader());
-                boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
-
-                if (AuthPolicyConf.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(AMImplementationType.AUTH_POLICY_CONF).add(bd.getBeanClassName());
-                }
-                if (AccessPolicyConf.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(AMImplementationType.ACCESS_POLICY_CONF).add(bd.getBeanClassName());
-                }
-            } catch (Throwable t) {
-                LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
-            }
-        });
-
-        classNames = Collections.unmodifiableMap(classNames);
-        LOG.debug("Implementation classes found: {}", classNames);
-
-        authPolicyClasses = Collections.unmodifiableMap(authPolicyClasses);
-        accessPolicyClasses = Collections.unmodifiableMap(accessPolicyClasses);
-    }
-
-    public Set<String> getClassNames(final String type) {
-        return classNames.get(type);
-    }
-
-    public Class<? extends AuthPolicyConf> getAuthPolicyConfClass(
-            final Class<? extends AuthPolicyConf> authPolicyConfClass) {
-
-        return authPolicyClasses.get(authPolicyConfClass);
-    }
-
-    public Class<? extends AccessPolicyConf> getAccessPolicyConfClass(
-            final Class<? extends AccessPolicyConf> accessPolicyConfClass) {
-
-        return accessPolicyClasses.get(accessPolicyConfClass);
-    }
-}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
index 6fb6f24..9a444d3 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
@@ -20,15 +20,12 @@ package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
-import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
-import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 
 public interface PolicyDAO extends DAO<Policy> {
 
@@ -42,12 +39,6 @@ public interface PolicyDAO extends DAO<Policy> {
 
     List<PullPolicy> findByPullCorrelationRule(Implementation correlationRule);
 
-    List<AuthPolicy> findByAuthPolicy(Implementation policy);
-
-    List<AccessPolicy> findByAccessPolicy(Implementation policy);
-
-    List<AttrReleasePolicy> findByAttrReleasePolicy(Implementation policy);
-
     List<PushPolicy> findByPushCorrelationRule(Implementation correlationRule);
 
     List<AccountPolicy> findByResource(ExternalResource resource);
@@ -57,5 +48,4 @@ public interface PolicyDAO extends DAO<Policy> {
     <T extends Policy> T save(T policy);
 
     <T extends Policy> void delete(T policy);
-
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java
index 0294443..1509722 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java
@@ -18,16 +18,11 @@
  */
 package org.apache.syncope.core.persistence.api.entity.policy;
 
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.common.lib.policy.AccessPolicyConf;
 
 public interface AccessPolicy extends Policy {
 
-    String getName();
-
-    void setName(String name);
-
-    Implementation getConfiguration();
-
-    void setConfiguration(Implementation configuration);
+    AccessPolicyConf getConf();
 
+    void setConf(AccessPolicyConf conf);
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java
index 3b3b5db..4b9fec4 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java
@@ -18,15 +18,11 @@
  */
 package org.apache.syncope.core.persistence.api.entity.policy;
 
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
 
 public interface AttrReleasePolicy extends Policy {
 
-    String getName();
+    AttrReleasePolicyConf getConf();
 
-    void setName(String name);
-
-    Implementation getConfiguration();
-
-    void setConfiguration(Implementation configuration);
+    void setConf(AttrReleasePolicyConf conf);
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
index d7c4a9a..46624e6 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
@@ -18,17 +18,11 @@
  */
 package org.apache.syncope.core.persistence.api.entity.policy;
 
-
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.common.lib.policy.AuthPolicyConf;
 
 public interface AuthPolicy extends Policy {
 
-    String getName();
-
-    void setName(String name);
-
-    Implementation getConfiguration();
-
-    void setConfiguration(Implementation configuration);
+    AuthPolicyConf getConf();
 
+    void setConf(AuthPolicyConf conf);
 }
diff --git a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
index d58f29a..4388d1c 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -44,25 +44,21 @@ under the License.
                   body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWit [...]
   <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
   
-  <!-- authentication policies -->
-  <Implementation id="MyDefaultAuthPolicyConf" type="AUTH_POLICY_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["LdapAuthenticationTest"]}'/>
-  <AuthPolicy id="659b9906-4b6e-4bc0-aca0-6809dff346d4" name="MyDefaultAuthPolicyConf" description="an authentication policy"/>
-  <AuthPolicy id="b912a0d4-a890-416f-9ab8-84ab077eb028" name="DefaultAuthPolicy" description="Default authentication policy"/>
+  <!-- Authentication policies -->
+  <AuthPolicy id="659b9906-4b6e-4bc0-aca0-6809dff346d4" description="MyDefaultAuthPolicyConf"
+              jsonConf='{"@class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["LdapAuthenticationTest"]}'/>
+  <AuthPolicy id="b912a0d4-a890-416f-9ab8-84ab077eb028" description="DefaultAuthPolicy"
+              jsonConf='{"@class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["LdapAuthenticationTest"]}'/>
 
-  <!-- access policies -->
-  <Implementation id="MyDefaultAccessPolicyConf" type="ACCESS_POLICY_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf","name":"MyDefaultAccessPolicyConf","enabled":true,"ssoEnabled":true}'/>
-  <AccessPolicy id="419935c7-deb3-40b3-8a9a-683037e523a2" name="MyDefaultAccessPolicyConf" description="an access policy"/>
+  <!-- Access policies -->
+  <AccessPolicy id="419935c7-deb3-40b3-8a9a-683037e523a2" description="MyDefaultAccessPolicyConf"
+                jsonConf='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf","name":"MyDefaultAccessPolicyConf","enabled":true,"ssoEnabled":true}'/>
 
   <!-- Attr Release Policies -->
-  <Implementation id="AllowedAttrReleasePolicyConf" type="ATTR_RELEASE_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"AllowedAttrReleasePolicy","allowedAttributes":["cn","givenName","uid"]}'/>
-  <AttrReleasePolicy id="319935c7-deb3-40b3-8a9a-683037e523a2" name="AllowedAttrReleasePolicy" description="allowed attribute release policy policy"/>
-
-  <Implementation id="DenyAttrReleasePolicyConf" type="ATTR_RELEASE_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"DenyAttrReleasePolicyConf"}'/>
-  <AttrReleasePolicy id="219935c7-deb3-40b3-8a9a-683037e523a2" name="DenyAttrReleasePolicy" description="deny attribute release policy policy"/>
+  <AttrReleasePolicy id="319935c7-deb3-40b3-8a9a-683037e523a2" description="AllowedAttrReleasePolicy"
+                     jsonConf='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"AllowedAttrReleasePolicy","allowedAttributes":["cn","givenName","uid"]}'/>
+  <AttrReleasePolicy id="219935c7-deb3-40b3-8a9a-683037e523a2" description="DenyAttrReleasePolicy"
+                     jsonConf='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"DenyAttrReleasePolicyConf"}'/>
   
   <!-- Authentication modules -->
   <AuthModule id="be456831-593d-4003-b273-4c3fb61700df" name="DefaultLDAPAuthModule" 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
index 1e8b9bd..972dcac 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
@@ -121,33 +121,6 @@ public class JPAPolicyDAO extends AbstractDAO<Policy> implements PolicyDAO {
     }
 
     @Override
-    public List<AuthPolicy> findByAuthPolicy(final Implementation configuration) {
-        TypedQuery<AuthPolicy> query = entityManager().createQuery("SELECT e FROM " + JPAAuthPolicy.class.
-                getSimpleName() + " e "
-                + "WHERE e.configuration=:configuration", AuthPolicy.class);
-        query.setParameter("configuration", configuration);
-        return query.getResultList();
-    }
-
-    @Override
-    public List<AccessPolicy> findByAccessPolicy(final Implementation configuration) {
-        TypedQuery<AccessPolicy> query = entityManager().createQuery("SELECT e FROM " + JPAAccessPolicy.class.
-                getSimpleName() + " e "
-                + "WHERE  e.configuration=:configuration", AccessPolicy.class);
-        query.setParameter("configuration", configuration);
-        return query.getResultList();
-    }
-
-    @Override
-    public List<AttrReleasePolicy> findByAttrReleasePolicy(final Implementation configuration) {
-        TypedQuery<AttrReleasePolicy> query = entityManager().createQuery(
-                "SELECT e FROM " + JPAAttrReleasePolicy.class.getSimpleName() + " e "
-                + "WHERE e.configuration=:configuration", AttrReleasePolicy.class);
-        query.setParameter("configuration", configuration);
-        return query.getResultList();
-    }
-
-    @Override
     public List<PushPolicy> findByPushCorrelationRule(final Implementation correlationRule) {
         TypedQuery<PushPolicy> query = entityManager().createQuery(
                 "SELECT DISTINCT e.pushPolicy FROM " + JPAPushCorrelationRuleEntity.class.getSimpleName() + " e "
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccessPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccessPolicy.java
index b5843a9..06e1ede 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccessPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccessPolicy.java
@@ -18,51 +18,34 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
-import org.apache.syncope.common.lib.types.AMImplementationType;
-import org.apache.syncope.core.persistence.api.entity.Implementation;
-import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
-import org.apache.syncope.core.persistence.jpa.entity.JPAImplementation;
-
-import javax.persistence.Column;
+import java.util.Optional;
 import javax.persistence.Entity;
-import javax.persistence.FetchType;
+import javax.persistence.Lob;
 import javax.persistence.Table;
-import javax.persistence.ManyToOne;
+import org.apache.syncope.common.lib.policy.AccessPolicyConf;
+import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
 @Entity
 @Table(name = JPAAccessPolicy.TABLE)
 public class JPAAccessPolicy extends AbstractPolicy implements AccessPolicy {
 
-    public static final String TABLE = "AccessPolicy";
-
     private static final long serialVersionUID = -4190607009908888884L;
 
-    @Column(unique = true, nullable = false)
-    private String name;
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    private JPAImplementation configuration;
-
-    @Override
-    public String getName() {
-        return name;
-    }
+    public static final String TABLE = "AccessPolicy";
 
-    @Override
-    public void setName(final String name) {
-        this.name = name;
-    }
+    @Lob
+    private String jsonConf;
 
     @Override
-    public Implementation getConfiguration() {
-        return configuration;
+    public AccessPolicyConf getConf() {
+        return jsonConf == null
+                ? null
+                : POJOHelper.deserialize(jsonConf, AccessPolicyConf.class);
     }
 
     @Override
-    public void setConfiguration(final Implementation configuration) {
-        checkType(configuration, JPAImplementation.class);
-        checkImplementationType(configuration, AMImplementationType.ACCESS_POLICY_CONF);
-        this.configuration = (JPAImplementation) configuration;
+    public void setConf(final AccessPolicyConf conf) {
+        jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null);
     }
-
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAttrReleasePolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAttrReleasePolicy.java
index d6d0ba3..48d515e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAttrReleasePolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAttrReleasePolicy.java
@@ -18,51 +18,34 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
-import org.apache.syncope.common.lib.types.AMImplementationType;
-import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
-import org.apache.syncope.core.persistence.jpa.entity.JPAImplementation;
-
-import javax.persistence.Column;
+import java.util.Optional;
 import javax.persistence.Entity;
-import javax.persistence.FetchType;
+import javax.persistence.Lob;
 import javax.persistence.Table;
-
-import javax.persistence.ManyToOne;
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
+import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
 @Entity
 @Table(name = JPAAttrReleasePolicy.TABLE)
 public class JPAAttrReleasePolicy extends AbstractPolicy implements AttrReleasePolicy {
 
-    public static final String TABLE = "AttrReleasePolicy";
-
     private static final long serialVersionUID = -4190607669908888884L;
 
-    @Column(unique = true, nullable = false)
-    private String name;
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    private JPAImplementation configuration;
-
-    @Override
-    public String getName() {
-        return name;
-    }
+    public static final String TABLE = "AttrReleasePolicy";
 
-    @Override
-    public void setName(final String name) {
-        this.name = name;
-    }
+    @Lob
+    private String jsonConf;
 
     @Override
-    public Implementation getConfiguration() {
-        return configuration;
+    public AttrReleasePolicyConf getConf() {
+        return jsonConf == null
+                ? null
+                : POJOHelper.deserialize(jsonConf, AttrReleasePolicyConf.class);
     }
 
     @Override
-    public void setConfiguration(final Implementation configuration) {
-        checkType(configuration, JPAImplementation.class);
-        checkImplementationType(configuration, AMImplementationType.ATTR_RELEASE_POLICY_CONF);
-        this.configuration = (JPAImplementation) configuration;
+    public void setConf(final AttrReleasePolicyConf conf) {
+        jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null);
     }
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAuthPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAuthPolicy.java
index 59263c2..4fff0db 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAuthPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAuthPolicy.java
@@ -18,51 +18,34 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
-import org.apache.syncope.common.lib.types.AMImplementationType;
-import org.apache.syncope.core.persistence.api.entity.Implementation;
-import org.apache.syncope.core.persistence.jpa.entity.JPAImplementation;
-
-import javax.persistence.Column;
+import java.util.Optional;
 import javax.persistence.Entity;
-import javax.persistence.FetchType;
+import javax.persistence.Lob;
 import javax.persistence.Table;
-import javax.persistence.ManyToOne;
+import org.apache.syncope.common.lib.policy.AuthPolicyConf;
 import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 
 @Entity
 @Table(name = JPAAuthPolicy.TABLE)
 public class JPAAuthPolicy extends AbstractPolicy implements AuthPolicy {
 
-    public static final String TABLE = "AuthPolicy";
-
     private static final long serialVersionUID = -4190607009908888884L;
 
-    @Column(unique = true, nullable = false)
-    private String name;
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    private JPAImplementation configuration;
-
-    @Override
-    public String getName() {
-        return name;
-    }
+    public static final String TABLE = "AuthPolicy";
 
-    @Override
-    public void setName(final String name) {
-        this.name = name;
-    }
+    @Lob
+    private String jsonConf;
 
     @Override
-    public Implementation getConfiguration() {
-        return configuration;
+    public AuthPolicyConf getConf() {
+        return jsonConf == null
+                ? null
+                : POJOHelper.deserialize(jsonConf, AuthPolicyConf.class);
     }
 
     @Override
-    public void setConfiguration(final Implementation configuration) {
-        checkType(configuration, JPAImplementation.class);
-        checkImplementationType(configuration, AMImplementationType.AUTH_POLICY_CONF);
-        this.configuration = (JPAImplementation) configuration;
+    public void setConf(final AuthPolicyConf conf) {
+        jsonConf = Optional.ofNullable(conf).map(POJOHelper::serialize).orElse(null);
     }
-
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtilsFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtilsFactory.java
index 1db66e9..8508b49 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtilsFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtilsFactory.java
@@ -18,26 +18,26 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
-import org.apache.syncope.common.lib.to.AccessPolicyTO;
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
+import org.apache.syncope.common.lib.policy.AuthPolicyTO;
 import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.policy.PushPolicyTO;
-import org.apache.syncope.common.lib.to.AttrReleasePolicyTO;
-import org.apache.syncope.common.lib.to.AuthPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PolicyUtils;
 import org.apache.syncope.core.persistence.api.entity.policy.PolicyUtilsFactory;
-import org.springframework.stereotype.Component;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
-import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
+import org.springframework.stereotype.Component;
 
 @Component
 public class JPAPolicyUtilsFactory implements PolicyUtilsFactory {
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java
index c4ea282..4e3140e 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java
@@ -24,16 +24,11 @@ import java.util.Set;
 import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
 import org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
-import org.apache.syncope.common.lib.types.AMImplementationType;
-import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
-import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
-import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 
 public class AbstractClientAppTest extends AbstractTest {
@@ -41,69 +36,41 @@ public class AbstractClientAppTest extends AbstractTest {
     @Autowired
     protected PolicyDAO policyDAO;
 
-    @Autowired
-    protected ImplementationDAO implementationDAO;
-
     protected AttrReleasePolicy buildAndSaveAttrRelPolicy() {
         AttrReleasePolicy attrRelPolicy = entityFactory.newEntity(AttrReleasePolicy.class);
-        attrRelPolicy.setName("AttrRelPolicyTest");
-        attrRelPolicy.setDescription("This is a sample access policy");
+        attrRelPolicy.setDescription("AttrRelPolicyTest");
 
         AllowedAttrReleasePolicyConf conf = new AllowedAttrReleasePolicyConf();
         conf.setName("Example Attr Rel Policy for an application");
-        conf.getAllowedAttributes().addAll(List.of("cn", "givenName"));
+        conf.getAllowedAttrs().addAll(List.of("cn", "givenName"));
+        attrRelPolicy.setConf(conf);
 
-        Implementation type = entityFactory.newEntity(Implementation.class);
-        type.setKey("AttrRelPolicyTest");
-        type.setEngine(ImplementationEngine.JAVA);
-        type.setType(AMImplementationType.ATTR_RELEASE_POLICY_CONF);
-        type.setBody(POJOHelper.serialize(conf));
-        type = implementationDAO.save(type);
-        attrRelPolicy.setConfiguration(type);
         return policyDAO.save(attrRelPolicy);
 
     }
 
     protected AccessPolicy buildAndSaveAccessPolicy() {
         AccessPolicy accessPolicy = entityFactory.newEntity(AccessPolicy.class);
-        accessPolicy.setName("AccessPolicyTest");
-        accessPolicy.setDescription("This is a sample access policy");
+        accessPolicy.setDescription("AccessPolicyTest");
 
         DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
         conf.setEnabled(true);
         conf.setName("Example Access Policy for an application");
-        conf.getRequiredAttributes().putAll(Map.of("attribute1", Set.of("value1", "value2")));
+        conf.getRequiredAttrs().putAll(Map.of("attribute1", Set.of("value1", "value2")));
         conf.setSsoEnabled(false);
+        accessPolicy.setConf(conf);
 
-        Implementation type = entityFactory.newEntity(Implementation.class);
-        type.setKey("AccessPolicyConfKey");
-        type.setEngine(ImplementationEngine.JAVA);
-        type.setType(AMImplementationType.ACCESS_POLICY_CONF);
-        type.setBody(POJOHelper.serialize(conf));
-        type = implementationDAO.save(type);
-
-        accessPolicy.setConfiguration(type);
         return policyDAO.save(accessPolicy);
-
     }
 
     protected AuthPolicy buildAndSaveAuthPolicy() {
         AuthPolicy authPolicy = entityFactory.newEntity(AuthPolicy.class);
-        authPolicy.setName("AuthPolicyTest");
-        authPolicy.setDescription("This is a sample authentication policy");
+        authPolicy.setDescription("AuthPolicyTest");
 
         DefaultAuthPolicyConf conf = new DefaultAuthPolicyConf();
         conf.getAuthModules().addAll(List.of("LdapAuthentication1", "DatabaseAuthentication2"));
+        authPolicy.setConf(conf);
 
-        Implementation type = entityFactory.newEntity(Implementation.class);
-        type.setKey("AuthPolicyConfKey");
-        type.setEngine(ImplementationEngine.JAVA);
-        type.setType(AMImplementationType.AUTH_POLICY_CONF);
-        type.setBody(POJOHelper.serialize(conf));
-        type = implementationDAO.save(type);
-
-        authPolicy.setConfiguration(type);
         return policyDAO.save(authPolicy);
     }
-
 }
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
index bf6ff38..21297d0 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
@@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.util.List;
-import org.apache.syncope.common.lib.types.AMImplementationType;
 import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
@@ -45,7 +44,7 @@ public class ImplementationTest extends AbstractTest {
         List<Implementation> implementations = implementationDAO.findAll();
         assertFalse(implementations.isEmpty());
 
-        assertEquals(22, implementations.size());
+        assertEquals(18, implementations.size());
 
         implementations = implementationDAO.findByType(IdMImplementationType.PULL_ACTIONS);
         assertEquals(1, implementations.size());
@@ -73,12 +72,6 @@ public class ImplementationTest extends AbstractTest {
 
         implementations = implementationDAO.findByType(IdMImplementationType.PUSH_CORRELATION_RULE);
         assertEquals(1, implementations.size());
-
-        implementations = implementationDAO.findByType(AMImplementationType.AUTH_POLICY_CONF);
-        assertEquals(1, implementations.size());
-
-        implementations = implementationDAO.findByType(AMImplementationType.ACCESS_POLICY_CONF);
-        assertEquals(1, implementations.size());
     }
 
     @Test
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
index 1ebc7c3..fe630bb 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
@@ -18,6 +18,16 @@
  */
 package org.apache.syncope.core.persistence.jpa.inner;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
 import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
 import org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
@@ -25,7 +35,6 @@ import org.apache.syncope.common.lib.policy.DefaultAuthPolicyCriteriaConf;
 import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.policy.DefaultPullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.DefaultPushCorrelationRuleConf;
-import org.apache.syncope.common.lib.types.AMImplementationType;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
 import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
@@ -37,6 +46,7 @@ import org.apache.syncope.core.persistence.api.dao.PullCorrelationRule;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PullCorrelationRuleEntity;
@@ -49,15 +59,6 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.Set;
-import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
-
 @Transactional("Master")
 public class PolicyTest extends AbstractTest {
 
@@ -122,21 +123,6 @@ public class PolicyTest extends AbstractTest {
         assertNotNull(attrReleasePolicy);
         attrReleasePolicy = policyDAO.find(UUID.randomUUID().toString());
         assertNull(attrReleasePolicy);
-
-    }
-
-    @Test
-    public void findByPolicyImpl() {
-        AccessPolicy accessPolicy = policyDAO.find("419935c7-deb3-40b3-8a9a-683037e523a2");
-        assertNotNull(accessPolicy);
-        AuthPolicy authPolicy = policyDAO.find("b912a0d4-a890-416f-9ab8-84ab077eb028");
-        assertNotNull(authPolicy);
-        AttrReleasePolicy attrReleasePolicy = policyDAO.find("319935c7-deb3-40b3-8a9a-683037e523a2");
-        assertNotNull(attrReleasePolicy);
-
-        assertFalse(policyDAO.findByAccessPolicy(accessPolicy.getConfiguration()).isEmpty());
-        assertFalse(policyDAO.findByAuthPolicy(authPolicy.getConfiguration()).isEmpty());
-        assertFalse(policyDAO.findByAttrReleasePolicy(attrReleasePolicy.getConfiguration()).isEmpty());
     }
 
     @Test
@@ -203,21 +189,13 @@ public class PolicyTest extends AbstractTest {
 
         int beforeCount = policyDAO.findAll().size();
         AccessPolicy accessPolicy = entityFactory.newEntity(AccessPolicy.class);
-        accessPolicy.setName("AttrReleasePolicyAllowEverything");
-        accessPolicy.setDescription("This is a sample attr release policy that releases everything");
+        accessPolicy.setDescription("AttrReleasePolicyAllowEverything");
 
         DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
-        conf.getRequiredAttributes().putAll(Map.of("cn", Set.of("syncope")));
+        conf.getRequiredAttrs().putAll(Map.of("cn", Set.of("syncope")));
         conf.setName("AttrReleasePolicyAllowEverything");
+        accessPolicy.setConf(conf);
 
-        Implementation type = entityFactory.newEntity(Implementation.class);
-        type.setKey("AttrReleasePolicyAllowEverything");
-        type.setEngine(ImplementationEngine.JAVA);
-        type.setType(AMImplementationType.ACCESS_POLICY_CONF);
-        type.setBody(POJOHelper.serialize(conf));
-        type = implementationDAO.save(type);
-
-        accessPolicy.setConfiguration(type);
         accessPolicy = policyDAO.save(accessPolicy);
 
         assertNotNull(accessPolicy);
@@ -228,8 +206,7 @@ public class PolicyTest extends AbstractTest {
 
         beforeCount = policyDAO.findAll().size();
         AuthPolicy authPolicy = entityFactory.newEntity(AuthPolicy.class);
-        authPolicy.setName("AuthPolicyTest");
-        authPolicy.setDescription("This is a sample authentication policy");
+        authPolicy.setDescription("AuthPolicyTest");
 
         DefaultAuthPolicyConf authPolicyConf = new DefaultAuthPolicyConf();
         authPolicyConf.getAuthModules().addAll(List.of("LdapAuthentication1", "DatabaseAuthentication2"));
@@ -237,14 +214,8 @@ public class PolicyTest extends AbstractTest {
         criteria.setName("DefaultConf");
         criteria.setAll(true);
         authPolicyConf.setCriteria(criteria);
-        Implementation authPolicyType = entityFactory.newEntity(Implementation.class);
-        authPolicyType.setKey("AuthPolicyConfKey");
-        authPolicyType.setEngine(ImplementationEngine.JAVA);
-        authPolicyType.setType(AMImplementationType.AUTH_POLICY_CONF);
-        authPolicyType.setBody(POJOHelper.serialize(authPolicyConf));
-        authPolicyType = implementationDAO.save(authPolicyType);
-
-        authPolicy.setConfiguration(authPolicyType);
+        authPolicy.setConf(authPolicyConf);
+
         authPolicy = policyDAO.save(authPolicy);
 
         assertNotNull(authPolicy);
@@ -254,30 +225,21 @@ public class PolicyTest extends AbstractTest {
         assertEquals(afterCount, beforeCount + 1);
 
         beforeCount = policyDAO.findAll().size();
-        AttrReleasePolicy attrReleasepolicy = entityFactory.newEntity(AttrReleasePolicy.class);
-        attrReleasepolicy.setName("AttrReleasePolicyAllowEverything");
-        attrReleasepolicy.setDescription("This is a sample attr release policy that releases everything");
+        AttrReleasePolicy attrReleasePolicy = entityFactory.newEntity(AttrReleasePolicy.class);
+        attrReleasePolicy.setDescription("AttrReleasePolicyAllowEverything");
 
         AllowedAttrReleasePolicyConf attrReleasePolicyConf = new AllowedAttrReleasePolicyConf();
-        attrReleasePolicyConf.getAllowedAttributes().addAll(List.of("*"));
+        attrReleasePolicyConf.getAllowedAttrs().addAll(List.of("*"));
         attrReleasePolicyConf.setName("AttrReleasePolicyAllowEverything");
+        attrReleasePolicy.setConf(attrReleasePolicyConf);
 
-        Implementation attrReleasePolicyType = entityFactory.newEntity(Implementation.class);
-        attrReleasePolicyType.setKey("AttrReleasePolicyAllowEverything");
-        attrReleasePolicyType.setEngine(ImplementationEngine.JAVA);
-        attrReleasePolicyType.setType(AMImplementationType.ATTR_RELEASE_POLICY_CONF);
-        attrReleasePolicyType.setBody(POJOHelper.serialize(attrReleasePolicyConf));
-        attrReleasePolicyType = implementationDAO.save(attrReleasePolicyType);
-
-        attrReleasepolicy.setConfiguration(attrReleasePolicyType);
-        attrReleasepolicy = policyDAO.save(attrReleasepolicy);
+        attrReleasePolicy = policyDAO.save(attrReleasePolicy);
 
-        assertNotNull(attrReleasepolicy);
-        assertNotNull(attrReleasepolicy.getKey());
+        assertNotNull(attrReleasePolicy);
+        assertNotNull(attrReleasePolicy.getKey());
 
         afterCount = policyDAO.findAll().size();
         assertEquals(afterCount, beforeCount + 1);
-
     }
 
     @Test
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 9e8b21b..8a5780c 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -45,24 +45,20 @@ under the License.
   <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
   
   <!-- Authentication policies -->
-  <Implementation id="MyDefaultAuthPolicyConf" type="AUTH_POLICY_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["LdapAuthenticationTest"]}'/>
-  <AuthPolicy id="659b9906-4b6e-4bc0-aca0-6809dff346d4" name="MyDefaultAuthPolicyConf" description="an authentication policy"/>
-  <AuthPolicy id="b912a0d4-a890-416f-9ab8-84ab077eb028" name="DefaultAuthPolicy" description="Default authentication policy"/>
+  <AuthPolicy id="659b9906-4b6e-4bc0-aca0-6809dff346d4" description="MyDefaultAuthPolicyConf"
+              jsonConf='{"@class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["LdapAuthenticationTest"]}'/>
+  <AuthPolicy id="b912a0d4-a890-416f-9ab8-84ab077eb028" description="DefaultAuthPolicy"
+              jsonConf='{"@class":"org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf","authModules":["LdapAuthenticationTest"]}'/>
 
   <!-- Access policies -->
-  <Implementation id="MyDefaultAccessPolicyConf" type="ACCESS_POLICY_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf","name":"MyDefaultAccessPolicyConf","enabled":true,"ssoEnabled":true}'/>
-  <AccessPolicy id="419935c7-deb3-40b3-8a9a-683037e523a2" name="MyDefaultAccessPolicyConf" description="an access policy"/>
+  <AccessPolicy id="419935c7-deb3-40b3-8a9a-683037e523a2" description="MyDefaultAccessPolicyConf"
+                jsonConf='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf","name":"MyDefaultAccessPolicyConf","enabled":true,"ssoEnabled":true}'/>
 
   <!-- Attr Release Policies -->
-  <Implementation id="AllowedAttrReleasePolicyConf" type="ATTR_RELEASE_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"AllowedAttrReleasePolicy","allowedAttributes":["cn","givenName","uid"]}'/>
-  <AttrReleasePolicy id="319935c7-deb3-40b3-8a9a-683037e523a2" name="AllowedAttrReleasePolicy" description="allowed attribute release policy policy"/>
-
-  <Implementation id="DenyAttrReleasePolicyConf" type="ATTR_RELEASE_CONF" engine="JAVA"
-                  body='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"DenyAttrReleasePolicyConf"}'/>
-  <AttrReleasePolicy id="219935c7-deb3-40b3-8a9a-683037e523a2" name="DenyAttrReleasePolicy" description="deny attribute release policy policy"/>
+  <AttrReleasePolicy id="319935c7-deb3-40b3-8a9a-683037e523a2" description="AllowedAttrReleasePolicy"
+                     jsonConf='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"AllowedAttrReleasePolicy","allowedAttributes":["cn","givenName","uid"]}'/>
+  <AttrReleasePolicy id="219935c7-deb3-40b3-8a9a-683037e523a2" description="DenyAttrReleasePolicy"
+                     jsonConf='{"@class":"org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf","name":"DenyAttrReleasePolicyConf"}'/>
 
   <!-- Authentication modules -->
   <AuthModule id="be456831-593d-4003-b273-4c3fb61700df" name="DefaultLDAPAuthModule"
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
index 5de0f13..99f240e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
@@ -21,12 +21,9 @@ package org.apache.syncope.core.provisioning.java.data;
 import java.lang.reflect.Modifier;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.policy.AccessPolicyConf;
-import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.RuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.AMImplementationType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
@@ -37,8 +34,6 @@ import org.apache.syncope.core.persistence.api.dao.PasswordRule;
 import org.apache.syncope.core.persistence.api.dao.Reportlet;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
-import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
-import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
 import org.apache.syncope.core.provisioning.api.LogicActions;
 import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder;
 import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
@@ -56,8 +51,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.apache.syncope.common.lib.policy.AuthPolicyConf;
-import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 
 @Component
 public class ImplementationDataBinderImpl implements ImplementationDataBinder {
@@ -156,17 +149,6 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
                     base = ProvisionSorter.class;
                     break;
 
-                case AMImplementationType.ACCESS_POLICY_CONF:
-                    base = AccessPolicy.class;
-                    break;
-
-                case AMImplementationType.AUTH_POLICY_CONF:
-                    base = AuthPolicy.class;
-                    break;
-
-                case AMImplementationType.ATTR_RELEASE_POLICY_CONF:
-                    base = AttrReleasePolicy.class;
-                    break;
                 default:
             }
 
@@ -176,30 +158,6 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
             }
 
             switch (implementation.getType()) {
-                case AMImplementationType.ACCESS_POLICY_CONF:
-                    AccessPolicyConf accessPolicyConf =
-                            POJOHelper.deserialize(implementation.getBody(), AccessPolicyConf.class);
-                    if (accessPolicyConf == null) {
-                        sce.getElements().add("Could not deserialize as AccessPolicy");
-                        throw sce;
-                    }
-                    break;
-                case AMImplementationType.ATTR_RELEASE_POLICY_CONF:
-                    AttrReleasePolicyConf policyConf =
-                            POJOHelper.deserialize(implementation.getBody(), AttrReleasePolicyConf.class);
-                    if (policyConf == null) {
-                        sce.getElements().add("Could not deserialize as AttrReleasePolicy");
-                        throw sce;
-                    }
-                    break;
-                case AMImplementationType.AUTH_POLICY_CONF:
-                    AuthPolicyConf authPolicyConf =
-                            POJOHelper.deserialize(implementation.getBody(), AuthPolicyConf.class);
-                    if (authPolicyConf == null) {
-                        sce.getElements().add("Could not deserialize as AuthPolicy");
-                        throw sce;
-                    }
-                    break;
                 case IdRepoImplementationType.REPORTLET:
                     ReportletConf reportlet = POJOHelper.deserialize(implementation.getBody(), ReportletConf.class);
                     if (reportlet == null) {
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 01093b2..8c51591 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
@@ -18,14 +18,15 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
+import java.util.stream.Collectors;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
 import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.policy.PushPolicyTO;
-import org.apache.syncope.common.lib.to.AccessPolicyTO;
-import org.apache.syncope.common.lib.to.AttrReleasePolicyTO;
-import org.apache.syncope.common.lib.to.AuthPolicyTO;
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
+import org.apache.syncope.common.lib.policy.AuthPolicyTO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
@@ -39,6 +40,7 @@ import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.policy.AccessPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.AttrReleasePolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PullCorrelationRuleEntity;
@@ -52,9 +54,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.stream.Collectors;
-import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
-
 @Component
 public class PolicyDataBinderImpl implements PolicyDataBinder {
 
@@ -207,14 +206,8 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
             AuthPolicy authPolicy = AuthPolicy.class.cast(result);
             AuthPolicyTO authPolicyTO = AuthPolicyTO.class.cast(policyTO);
 
-            authPolicy.setName(authPolicyTO.getKey());
-            Implementation configuration = implementationDAO.find(authPolicyTO.getConfiguration());
-            if (configuration == null) {
-                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
-                        authPolicyTO.getConfiguration());
-            } else {
-                authPolicy.setConfiguration(configuration);
-            }
+            authPolicy.setDescription(authPolicyTO.getKey());
+            authPolicy.setConf(authPolicyTO.getConf());
         } else if (policyTO instanceof AccessPolicyTO) {
             if (result == null) {
                 result = (T) entityFactory.newEntity(AccessPolicy.class);
@@ -223,14 +216,8 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
             AccessPolicy accessPolicy = AccessPolicy.class.cast(result);
             AccessPolicyTO accessPolicyTO = AccessPolicyTO.class.cast(policyTO);
 
-            accessPolicy.setName(accessPolicyTO.getKey());
-            Implementation configuration = implementationDAO.find(accessPolicyTO.getConfiguration());
-            if (configuration == null) {
-                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
-                        accessPolicyTO.getConfiguration());
-            } else {
-                accessPolicy.setConfiguration(configuration);
-            }
+            accessPolicy.setDescription(accessPolicyTO.getKey());
+            accessPolicy.setConf(accessPolicyTO.getConf());
         } else if (policyTO instanceof AttrReleasePolicyTO) {
             if (result == null) {
                 result = (T) entityFactory.newEntity(AttrReleasePolicy.class);
@@ -239,14 +226,8 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
             AttrReleasePolicy attrReleasePolicy = AttrReleasePolicy.class.cast(result);
             AttrReleasePolicyTO attrReleasePolicyTO = AttrReleasePolicyTO.class.cast(policyTO);
 
-            attrReleasePolicy.setName(attrReleasePolicyTO.getKey());
-            Implementation configuration = implementationDAO.find(attrReleasePolicyTO.getConfiguration());
-            if (configuration == null) {
-                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
-                        attrReleasePolicyTO.getConfiguration());
-            } else {
-                attrReleasePolicy.setConfiguration(configuration);
-            }
+            attrReleasePolicy.setDescription(attrReleasePolicyTO.getKey());
+            attrReleasePolicy.setConf(attrReleasePolicyTO.getConf());
         }
 
         if (result != null) {
@@ -314,18 +295,15 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
                     put(rule.getAnyType().getKey(), rule.getImplementation().getKey()));
         } else if (policy instanceof AuthPolicy) {
             AuthPolicyTO authPolicyTO = new AuthPolicyTO();
-            authPolicyTO.setConfiguration(((AuthPolicy) policy).getConfiguration() == null
-                    ? null : ((AuthPolicy) policy).getConfiguration().getKey());
+            authPolicyTO.setConf(((AuthPolicy) policy).getConf());
             policyTO = (T) authPolicyTO;
         } else if (policy instanceof AccessPolicy) {
             AccessPolicyTO accessPolicyTO = new AccessPolicyTO();
-            accessPolicyTO.setConfiguration(((AccessPolicy) policy).getConfiguration() == null
-                    ? null : ((AccessPolicy) policy).getConfiguration().getKey());
+            accessPolicyTO.setConf(((AccessPolicy) policy).getConf());
             policyTO = (T) accessPolicyTO;
         } else if (policy instanceof AttrReleasePolicy) {
             AttrReleasePolicyTO attrReleasePolicyTO = new AttrReleasePolicyTO();
-            attrReleasePolicyTO.setConfiguration(((AttrReleasePolicy) policy).getConfiguration() == null
-                    ? null : ((AttrReleasePolicy) policy).getConfiguration().getKey());
+            attrReleasePolicyTO.setConf(((AttrReleasePolicy) policy).getConf());
             policyTO = (T) attrReleasePolicyTO;
         }
 
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/wa/WAClientAppBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/wa/WAClientAppBinderImpl.java
index 5636892..4f7c225 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/wa/WAClientAppBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/wa/WAClientAppBinderImpl.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.provisioning.java.data.wa;
 import org.apache.syncope.common.lib.wa.WAClientApp;
 import org.apache.syncope.core.persistence.api.entity.auth.ClientApp;
 import org.apache.syncope.core.provisioning.api.data.ClientAppDataBinder;
-import org.apache.syncope.core.spring.ImplementationManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -43,27 +42,21 @@ public class WAClientAppBinderImpl implements WAClientAppBinder {
 
         try {
             if (clientApp.getAuthPolicy() != null) {
-                waClientApp.setAuthPolicyConf(
-                        ImplementationManager.build((clientApp.getAuthPolicy()).getConfiguration()));
+                waClientApp.setAuthPolicyConf((clientApp.getAuthPolicy()).getConf());
             } else if (clientApp.getRealm().getAuthPolicy() != null) {
-                waClientApp.setAuthPolicyConf(
-                        ImplementationManager.build((clientApp.getRealm().getAuthPolicy()).getConfiguration()));
+                waClientApp.setAuthPolicyConf((clientApp.getRealm().getAuthPolicy()).getConf());
             }
 
             if (clientApp.getAccessPolicy() != null) {
-                waClientApp.setAccessPolicyConf(
-                        ImplementationManager.build((clientApp.getAccessPolicy()).getConfiguration()));
+                waClientApp.setAccessPolicyConf((clientApp.getAccessPolicy()).getConf());
             } else if (clientApp.getRealm().getAccessPolicy() != null) {
-                waClientApp.setAccessPolicyConf(
-                        ImplementationManager.build((clientApp.getRealm().getAccessPolicy()).getConfiguration()));
+                waClientApp.setAccessPolicyConf((clientApp.getRealm().getAccessPolicy()).getConf());
             }
 
             if (clientApp.getAttrReleasePolicy() != null) {
-                waClientApp.setAttrReleasePolicyConf(
-                        ImplementationManager.build((clientApp.getAttrReleasePolicy()).getConfiguration()));
+                waClientApp.setAttrReleasePolicyConf((clientApp.getAttrReleasePolicy()).getConf());
             } else if (clientApp.getRealm().getAttrReleasePolicy() != null) {
-                waClientApp.setAttrReleasePolicyConf(
-                        ImplementationManager.build((clientApp.getRealm().getAttrReleasePolicy()).getConfiguration()));
+                waClientApp.setAttrReleasePolicyConf((clientApp.getRealm().getAttrReleasePolicy()).getConf());
             }
         } catch (Exception e) {
             LOG.error("While building the configuration from an application's policy ", e);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 530113f..90a865a 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -65,7 +65,7 @@ import org.apache.syncope.common.lib.request.UserCR;
 import org.apache.syncope.common.lib.to.SchemaTO;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.Attr;
-import org.apache.syncope.common.lib.to.AccessPolicyTO;
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
@@ -76,7 +76,7 @@ import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
-import org.apache.syncope.common.lib.to.AuthPolicyTO;
+import org.apache.syncope.common.lib.policy.AuthPolicyTO;
 import org.apache.syncope.common.lib.to.SAML2IdPMetadataTO;
 import org.apache.syncope.common.lib.to.client.ClientAppTO;
 import org.apache.syncope.common.lib.to.client.OIDCRPTO;
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ClientAppITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ClientAppITCase.java
index 3ee1586..f0caecf 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ClientAppITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ClientAppITCase.java
@@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.fail;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.to.AccessPolicyTO;
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
 import org.apache.syncope.common.lib.to.client.OIDCRPTO;
 import org.apache.syncope.common.lib.to.client.SAML2SPTO;
 import org.apache.syncope.common.lib.types.ClientAppType;
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
index 817e121..9df4990 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
@@ -36,10 +36,9 @@ import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
 import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.policy.PushPolicyTO;
-import org.apache.syncope.common.lib.to.AccessPolicyTO;
-import org.apache.syncope.common.lib.to.AttrReleasePolicyTO;
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.AMImplementationType;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
@@ -51,109 +50,48 @@ import org.apache.syncope.fit.AbstractITCase;
 import org.apache.syncope.fit.core.reference.DummyPullCorrelationRule;
 import org.apache.syncope.fit.core.reference.DummyPushCorrelationRule;
 import org.junit.jupiter.api.Test;
-import org.junit.platform.commons.util.StringUtils;
 import javax.ws.rs.core.Response;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Set;
+import org.apache.syncope.common.lib.policy.AuthPolicyTO;
 import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
-import org.apache.syncope.common.lib.to.AuthPolicyTO;
 
 public class PolicyITCase extends AbstractITCase {
 
     private static AuthPolicyTO buildAuthPolicyTO() {
-        String authPolicyName = "TestAuthPolicy" + getUUIDString();
-        ImplementationTO implementationTO = null;
-        try {
-            implementationTO = implementationService.read(AMImplementationType.AUTH_POLICY_CONF, authPolicyName);
-        } catch (SyncopeClientException e) {
-            if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
-                implementationTO = new ImplementationTO();
-                implementationTO.setKey(authPolicyName);
-                implementationTO.setEngine(ImplementationEngine.JAVA);
-                implementationTO.setType(AMImplementationType.AUTH_POLICY_CONF);
-
-                DefaultAuthPolicyConf conf = new DefaultAuthPolicyConf();
-                conf.getAuthModules().addAll(List.of("LdapAuthentication1"));
-                implementationTO.setBody(POJOHelper.serialize(conf));
-
-                Response response = implementationService.create(implementationTO);
-                implementationTO = implementationService.read(
-                        implementationTO.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
-                assertNotNull(implementationTO);
-            }
-        }
-        assertNotNull(implementationTO);
-
         AuthPolicyTO policy = new AuthPolicyTO();
         policy.setDescription("Test Authentication policy");
-        policy.setKey(implementationTO.getKey());
+
+        DefaultAuthPolicyConf conf = new DefaultAuthPolicyConf();
+        conf.getAuthModules().addAll(List.of("LdapAuthentication1"));
+        policy.setConf(conf);
 
         return policy;
     }
 
     private static AttrReleasePolicyTO buildAttributeReleasePolicyTO(final String policyName) {
-        ImplementationTO implementationTO = null;
-        try {
-            implementationTO = implementationService.read(AMImplementationType.ATTR_RELEASE_POLICY_CONF, policyName);
-        } catch (SyncopeClientException e) {
-            if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
-                implementationTO = new ImplementationTO();
-                implementationTO.setKey(policyName);
-                implementationTO.setEngine(ImplementationEngine.JAVA);
-                implementationTO.setType(AMImplementationType.ATTR_RELEASE_POLICY_CONF);
-
-                AllowedAttrReleasePolicyConf conf = new AllowedAttrReleasePolicyConf();
-                conf.setName("MyDefaultAttrReleasePolicyConf");
-                conf.getAllowedAttributes().addAll(List.of("cn", "givenName"));
-                implementationTO.setBody(POJOHelper.serialize(conf));
-
-                Response response = implementationService.create(implementationTO);
-                implementationTO = implementationService.read(
-                        implementationTO.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
-                assertNotNull(implementationTO);
-            }
-        }
-        assertNotNull(implementationTO);
-
         AttrReleasePolicyTO policy = new AttrReleasePolicyTO();
         policy.setDescription("Test Attribute Release policy");
-        policy.setKey(implementationTO.getKey());
+
+        AllowedAttrReleasePolicyConf conf = new AllowedAttrReleasePolicyConf();
+        conf.setName("MyDefaultAttrReleasePolicyConf");
+        conf.getAllowedAttrs().addAll(List.of("cn", "givenName"));
+        policy.setConf(conf);
 
         return policy;
     }
 
     private static AccessPolicyTO buildAccessPolicyTO() {
-        final String accessPolicyName = "TestAccessPolicy" + getUUIDString();
-
-        ImplementationTO implementationTO = null;
-        try {
-            implementationTO = implementationService.read(AMImplementationType.ACCESS_POLICY_CONF, accessPolicyName);
-        } catch (SyncopeClientException e) {
-            if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
-                implementationTO = new ImplementationTO();
-                implementationTO.setKey(accessPolicyName);
-                implementationTO.setEngine(ImplementationEngine.JAVA);
-                implementationTO.setType(AMImplementationType.ACCESS_POLICY_CONF);
-
-                DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
-                conf.setEnabled(true);
-                conf.setName("TestAccessPolicyConf");
-                conf.getRequiredAttributes().put("cn", Set.of("admin", "Admin", "TheAdmin"));
-                implementationTO.setBody(POJOHelper.serialize(conf));
-
-                Response response = implementationService.create(implementationTO);
-                implementationTO = implementationService.read(
-                        implementationTO.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
-                assertNotNull(implementationTO);
-            }
-        }
-        assertNotNull(implementationTO);
-
         AccessPolicyTO policy = new AccessPolicyTO();
         policy.setDescription("Test Access policy");
-        policy.setKey(implementationTO.getKey());
+
+        DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
+        conf.setEnabled(true);
+        conf.setName("TestAccessPolicyConf");
+        conf.getRequiredAttrs().put("cn", Set.of("admin", "Admin", "TheAdmin"));
+        policy.setConf(conf);
 
         return policy;
     }
@@ -329,23 +267,15 @@ public class PolicyITCase extends AbstractITCase {
         assertNotNull(newAuthPolicyTO);
         newAuthPolicyTO = createPolicy(PolicyType.AUTH, newAuthPolicyTO);
 
-        ImplementationTO authPolicyImplementationTO = implementationService.read(AMImplementationType.AUTH_POLICY_CONF, "MyDefaultAuthPolicyConf");
-        assertNotNull(authPolicyImplementationTO);
-        assertFalse(StringUtils.isBlank(authPolicyImplementationTO.getBody()));
-
-        DefaultAuthPolicyConf authPolicyConf =
-                POJOHelper.deserialize(authPolicyImplementationTO.getBody(), DefaultAuthPolicyConf.class);
-        assertNotNull(authPolicyConf);
+        DefaultAuthPolicyConf authPolicyConf = (DefaultAuthPolicyConf) newAuthPolicyTO.getConf();
         authPolicyConf.getAuthModules().add("LdapAuthentication");
-        authPolicyImplementationTO.setBody(POJOHelper.serialize(authPolicyConf));
 
         // update new authentication policy
         policyService.update(PolicyType.AUTH, newAuthPolicyTO);
         newAuthPolicyTO = policyService.read(PolicyType.AUTH, newAuthPolicyTO.getKey());
         assertNotNull(newAuthPolicyTO);
 
-        authPolicyConf = POJOHelper.deserialize(authPolicyImplementationTO.getBody(),
-                DefaultAuthPolicyConf.class);
+        authPolicyConf = (DefaultAuthPolicyConf) newAuthPolicyTO.getConf();
         assertNotNull(authPolicyConf);
         assertEquals(2, authPolicyConf.getAuthModules().size());
         assertTrue(authPolicyConf.getAuthModules().contains("LdapAuthentication"));
@@ -353,68 +283,45 @@ public class PolicyITCase extends AbstractITCase {
 
     @Test
     public void updateAccessPolicy() {
-        AccessPolicyTO globalAccessPolicyTO =
-                policyService.read(PolicyType.ACCESS, "419935c7-deb3-40b3-8a9a-683037e523a2");
-        assertNotNull(globalAccessPolicyTO);
-
         AccessPolicyTO newAccessPolicyTO = buildAccessPolicyTO();
         newAccessPolicyTO = createPolicy(PolicyType.ACCESS, newAccessPolicyTO);
         assertNotNull(newAccessPolicyTO);
 
-        ImplementationTO accessPolicyImplementationTO = implementationService.read(AMImplementationType.ACCESS_POLICY_CONF, "MyDefaultAccessPolicyConf");
-        assertNotNull(accessPolicyImplementationTO);
-        assertFalse(StringUtils.isBlank(accessPolicyImplementationTO.getBody()));
-
-        DefaultAccessPolicyConf accessPolicyConf =
-                POJOHelper.deserialize(accessPolicyImplementationTO.getBody(), DefaultAccessPolicyConf.class);
-        assertNotNull(accessPolicyConf);
-        accessPolicyConf.getRequiredAttributes().put("ou", Set.of("test"));
-        accessPolicyConf.getRequiredAttributes().put("cn", Set.of("admin", "Admin"));
-        accessPolicyImplementationTO.setBody(POJOHelper.serialize(accessPolicyConf));
+        DefaultAccessPolicyConf accessPolicyConf = (DefaultAccessPolicyConf) newAccessPolicyTO.getConf();
+        accessPolicyConf.getRequiredAttrs().put("ou", Set.of("test"));
+        accessPolicyConf.getRequiredAttrs().put("cn", Set.of("admin", "Admin"));
 
         // update new authentication policy
         policyService.update(PolicyType.ACCESS, newAccessPolicyTO);
         newAccessPolicyTO = policyService.read(PolicyType.ACCESS, newAccessPolicyTO.getKey());
         assertNotNull(newAccessPolicyTO);
 
-        accessPolicyConf = POJOHelper.deserialize(accessPolicyImplementationTO.getBody(), DefaultAccessPolicyConf.class);
-        assertEquals(2, accessPolicyConf.getRequiredAttributes().size());
-        assertNotNull(accessPolicyConf.getRequiredAttributes().get("cn"));
-        assertNotNull(accessPolicyConf.getRequiredAttributes().get("ou"));
-
+        accessPolicyConf = (DefaultAccessPolicyConf) newAccessPolicyTO.getConf();
+        assertEquals(2, accessPolicyConf.getRequiredAttrs().size());
+        assertNotNull(accessPolicyConf.getRequiredAttrs().get("cn"));
+        assertNotNull(accessPolicyConf.getRequiredAttrs().get("ou"));
     }
 
     @Test
     public void updateAttrReleasePolicy() {
-        AttrReleasePolicyTO policyTO =
-                policyService.read(PolicyType.ATTR_RELEASE, "319935c7-deb3-40b3-8a9a-683037e523a2");
-        assertNotNull(policyTO);
-
-        final String policyName = "TestAttrReleasePolicy" + getUUIDString();
+        String policyName = "TestAttrReleasePolicy" + getUUIDString();
         AttrReleasePolicyTO newPolicyTO = buildAttributeReleasePolicyTO(policyName);
         newPolicyTO = createPolicy(PolicyType.ATTR_RELEASE, newPolicyTO);
         assertNotNull(newPolicyTO);
 
-        ImplementationTO implementationTO = implementationService.read(AMImplementationType.ATTR_RELEASE_POLICY_CONF, policyName);
-        assertNotNull(implementationTO);
-        assertFalse(StringUtils.isBlank(implementationTO.getBody()));
-
-        AllowedAttrReleasePolicyConf policyConf =
-                POJOHelper.deserialize(implementationTO.getBody(), AllowedAttrReleasePolicyConf.class);
-        assertNotNull(policyConf);
-        policyConf.getAllowedAttributes().add("postalCode");
-        implementationTO.setBody(POJOHelper.serialize(policyConf));
+        AllowedAttrReleasePolicyConf policyConf = (AllowedAttrReleasePolicyConf) newPolicyTO.getConf();
+        policyConf.getAllowedAttrs().add("postalCode");
 
         // update new policy
         policyService.update(PolicyType.ATTR_RELEASE, newPolicyTO);
         newPolicyTO = policyService.read(PolicyType.ATTR_RELEASE, newPolicyTO.getKey());
         assertNotNull(newPolicyTO);
 
-        policyConf = POJOHelper.deserialize(implementationTO.getBody(), AllowedAttrReleasePolicyConf.class);
-        assertEquals(3, policyConf.getAllowedAttributes().size());
-        assertTrue(policyConf.getAllowedAttributes().contains("cn"));
-        assertTrue(policyConf.getAllowedAttributes().contains("postalCode"));
-        assertTrue(policyConf.getAllowedAttributes().contains("givenName"));
+        policyConf = (AllowedAttrReleasePolicyConf) newPolicyTO.getConf();
+        assertEquals(3, policyConf.getAllowedAttrs().size());
+        assertTrue(policyConf.getAllowedAttrs().contains("cn"));
+        assertTrue(policyConf.getAllowedAttrs().contains("postalCode"));
+        assertTrue(policyConf.getAllowedAttrs().contains("givenName"));
 
     }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index 884eaee..a3dfd886 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -39,13 +39,12 @@ import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
-import org.apache.syncope.common.lib.to.AccessPolicyTO;
-import org.apache.syncope.common.lib.to.AttrReleasePolicyTO;
-import org.apache.syncope.common.lib.to.AuthPolicyTO;
+import org.apache.syncope.common.lib.policy.AccessPolicyTO;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
+import org.apache.syncope.common.lib.policy.AuthPolicyTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
-import org.apache.syncope.common.lib.types.AMImplementationType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.common.lib.types.PolicyType;
@@ -217,17 +216,9 @@ public class RealmITCase extends AbstractITCase {
         DefaultAuthPolicyConf ruleConf = new DefaultAuthPolicyConf();
         ruleConf.getAuthModules().addAll(List.of("LdapAuthentication1"));
 
-        ImplementationTO rule = new ImplementationTO();
-        rule.setKey("TestAuthPolicy" + getUUIDString());
-        rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(AMImplementationType.AUTH_POLICY_CONF);
-        rule.setBody(POJOHelper.serialize(ruleConf));
-        Response response = implementationService.create(rule);
-        rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
-
         AuthPolicyTO policy = new AuthPolicyTO();
         policy.setDescription("Test Authentication policy");
-        policy.setKey(rule.getKey());
+        policy.setConf(ruleConf);
         policy = createPolicy(PolicyType.AUTH, policy);
         assertNotNull(policy);
 
@@ -235,7 +226,7 @@ public class RealmITCase extends AbstractITCase {
         RealmTO realm = new RealmTO();
         realm.setName("withAuthPolicy");
 
-        response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
+        Response response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
         RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
         assertNotNull(actuals);
         assertTrue(actuals.length > 0);
@@ -266,19 +257,11 @@ public class RealmITCase extends AbstractITCase {
         DefaultAccessPolicyConf ruleConf = new DefaultAccessPolicyConf();
         ruleConf.setEnabled(true);
         ruleConf.setName("TestAccessPolicyConf" + getUUIDString());
-        ruleConf.getRequiredAttributes().put("cn", Set.of("admin", "Admin", "TheAdmin"));
-
-        ImplementationTO rule = new ImplementationTO();
-        rule.setKey("TestAccessPolicy" + getUUIDString());
-        rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(AMImplementationType.ACCESS_POLICY_CONF);
-        rule.setBody(POJOHelper.serialize(ruleConf));
-        Response response = implementationService.create(rule);
-        rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+        ruleConf.getRequiredAttrs().put("cn", Set.of("admin", "Admin", "TheAdmin"));
 
         AccessPolicyTO policy = new AccessPolicyTO();
         policy.setDescription("Test Access policy");
-        policy.setKey(rule.getKey());
+        policy.setConf(ruleConf);
         policy = createPolicy(PolicyType.ACCESS, policy);
         assertNotNull(policy);
 
@@ -286,7 +269,7 @@ public class RealmITCase extends AbstractITCase {
         RealmTO realm = new RealmTO();
         realm.setName("withAccessPolicy");
 
-        response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
+        Response response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
         RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
         assertNotNull(actuals);
         assertTrue(actuals.length > 0);
@@ -316,19 +299,11 @@ public class RealmITCase extends AbstractITCase {
         // 1. create attribute release policy
         AllowedAttrReleasePolicyConf ruleConf = new AllowedAttrReleasePolicyConf();
         ruleConf.setName("MyDefaultAttrReleasePolicyConf" + getUUIDString());
-        ruleConf.getAllowedAttributes().addAll(List.of("cn", "givenName"));
-
-        ImplementationTO rule = new ImplementationTO();
-        rule.setKey("TestAttrReleasePolicy" + getUUIDString());
-        rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(AMImplementationType.ATTR_RELEASE_POLICY_CONF);
-        rule.setBody(POJOHelper.serialize(ruleConf));
-        Response response = implementationService.create(rule);
-        rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
+        ruleConf.getAllowedAttrs().addAll(List.of("cn", "givenName"));
 
         AttrReleasePolicyTO policy = new AttrReleasePolicyTO();
         policy.setDescription("Test Attribute Release policy");
-        policy.setKey(rule.getKey());
+        policy.setConf(ruleConf);
         policy = createPolicy(PolicyType.ATTR_RELEASE, policy);
         assertNotNull(policy);
 
@@ -336,7 +311,7 @@ public class RealmITCase extends AbstractITCase {
         RealmTO realm = new RealmTO();
         realm.setName("withAttrReleasePolicy");
 
-        response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
+        Response response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
         RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
         assertNotNull(actuals);
         assertTrue(actuals.length > 0);
diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
index 15498fe..ce944a7 100644
--- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
+++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.wa.bootstrap;
 
-import org.apache.syncope.wa.WARestClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWAPropertySourceLocator.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWAPropertySourceLocator.java
index 94e50c8..76ff64d 100644
--- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWAPropertySourceLocator.java
+++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWAPropertySourceLocator.java
@@ -46,7 +46,6 @@ import org.apache.syncope.common.lib.auth.StaticAuthModuleConf;
 import org.apache.syncope.common.lib.auth.SyncopeAuthModuleConf;
 import org.apache.syncope.common.lib.auth.U2FAuthModuleConf;
 import org.apache.syncope.common.rest.api.service.AuthModuleService;
-import org.apache.syncope.wa.WARestClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/WARestClient.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java
similarity index 98%
rename from wa/bootstrap/src/main/java/org/apache/syncope/wa/WARestClient.java
rename to wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java
index aa323d4..4ad7369 100644
--- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/WARestClient.java
+++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa;
+package org.apache.syncope.wa.bootstrap;
 
 import org.apereo.cas.util.spring.ApplicationContextProvider;
 import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/RegisteredServiceMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/RegisteredServiceMapper.java
deleted file mode 100644
index 2746793..0000000
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/RegisteredServiceMapper.java
+++ /dev/null
@@ -1,205 +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.
- */
-package org.apache.syncope.wa.starter;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf;
-import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
-import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
-import org.apache.syncope.common.lib.policy.DefaultAuthPolicyCriteriaConf;
-import org.apache.syncope.common.lib.wa.WAClientApp;
-import org.apache.syncope.common.lib.to.client.OIDCRPTO;
-import org.apache.syncope.common.lib.to.client.SAML2SPTO;
-import org.apache.syncope.common.lib.types.OIDCSubjectType;
-import org.apache.syncope.common.lib.types.SAML2SPNameId;
-import org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy;
-import org.apereo.cas.services.DefaultRegisteredServiceAuthenticationPolicy;
-import org.apereo.cas.services.DenyAllAttributeReleasePolicy;
-import org.apereo.cas.services.OidcRegisteredService;
-import org.apereo.cas.services.RegisteredService;
-import org.apereo.cas.services.RegisteredServiceAccessStrategy;
-import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
-import org.apereo.cas.services.AnyAuthenticationHandlerRegisteredServiceAuthenticationPolicyCriteria;
-import org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy;
-import org.apereo.cas.support.saml.services.SamlRegisteredService;
-
-public final class RegisteredServiceMapper {
-
-    private RegisteredServiceMapper() {
-        // private constructor for static utility class
-    }
-
-    public static RegisteredService toRegisteredService(final WAClientApp clientApp) {
-        DefaultRegisteredServiceAuthenticationPolicy authPolicy = new DefaultRegisteredServiceAuthenticationPolicy();
-        AnyAuthenticationHandlerRegisteredServiceAuthenticationPolicyCriteria criteria =
-                new AnyAuthenticationHandlerRegisteredServiceAuthenticationPolicyCriteria();
-        criteria.setTryAll(((DefaultAuthPolicyCriteriaConf) clientApp.getAuthPolicyConf().getCriteria()).isAll());
-        authPolicy.setCriteria(criteria);
-
-        RegisteredServiceAccessStrategy accessStrategy = new DefaultRegisteredServiceAccessStrategy(
-                clientApp.getAccessPolicyConf().isEnabled(), clientApp.getAccessPolicyConf().isSsoEnabled());
-        accessStrategy.getRequiredAttributes().putAll(clientApp.getAccessPolicyConf().getRequiredAttributes());
-
-        RegisteredServiceAttributeReleasePolicy attributeReleasePolicy;
-        if (clientApp.getAttrReleasePolicyConf() != null
-                && clientApp.getAttrReleasePolicyConf() instanceof AllowedAttrReleasePolicyConf
-                && !((AllowedAttrReleasePolicyConf) clientApp.getAttrReleasePolicyConf()).
-                        getAllowedAttributes().isEmpty()) {
-
-            attributeReleasePolicy = new ReturnAllowedAttributeReleasePolicy();
-            ((AllowedAttrReleasePolicyConf) clientApp.getAttrReleasePolicyConf()).getAllowedAttributes();
-            ((ReturnAllowedAttributeReleasePolicy) attributeReleasePolicy).getAllowedAttributes().addAll(
-                    ((AllowedAttrReleasePolicyConf) clientApp.getAttrReleasePolicyConf()).getAllowedAttributes());
-        } else {
-            attributeReleasePolicy = new DenyAllAttributeReleasePolicy();
-        }
-
-        if (clientApp.getClientAppTO() instanceof OIDCRPTO) {
-            OIDCRPTO rp = OIDCRPTO.class.cast(clientApp.getClientAppTO());
-            OidcRegisteredService service = new OidcRegisteredService();
-
-            String redirectURIs = String.join("|", rp.getRedirectUris());
-            service.setServiceId(redirectURIs);
-            service.setName(rp.getName());
-            service.setDescription(rp.getDescription());
-            service.setAccessStrategy(accessStrategy);
-            service.setAuthenticationPolicy(authPolicy);
-            service.setAttributeReleasePolicy(attributeReleasePolicy);
-
-            service.setClientId(rp.getClientId());
-            service.setClientSecret(rp.getClientSecret());
-            service.setSignIdToken(rp.isSignIdToken());
-            service.setJwks(rp.getJwks());
-            service.setSubjectType(rp.getSubjectType().name());
-            service.setRedirectUrl(redirectURIs);
-            service.setSupportedGrantTypes((HashSet<String>) rp.getSupportedGrantTypes());
-            service.setSupportedResponseTypes((HashSet<String>) rp.getSupportedResponseTypes());
-
-            return service;
-        } else if (clientApp.getClientAppTO() instanceof SAML2SPTO) {
-            SAML2SPTO sp = SAML2SPTO.class.cast(clientApp.getClientAppTO());
-            SamlRegisteredService service = new SamlRegisteredService();
-
-            service.setServiceId(sp.getEntityId());
-            service.setName(sp.getName());
-            service.setDescription(sp.getDescription());
-            service.setAccessStrategy(accessStrategy);
-            service.setAuthenticationPolicy(authPolicy);
-            service.setAttributeReleasePolicy(attributeReleasePolicy);
-
-            service.setMetadataLocation(sp.getMetadataLocation());
-            service.setMetadataSignatureLocation(sp.getMetadataSignatureLocation());
-            service.setSignAssertions(sp.isSignAssertions());
-            service.setSignResponses(sp.isSignResponses());
-            service.setEncryptionOptional(sp.isEncryptionOptional());
-            service.setEncryptAssertions(sp.isEncryptAssertions());
-            service.setRequiredAuthenticationContextClass(sp.getRequiredAuthenticationContextClass());
-            service.setRequiredNameIdFormat(sp.getRequiredNameIdFormat().getNameId());
-            service.setSkewAllowance(sp.getSkewAllowance());
-            service.setNameIdQualifier(sp.getNameIdQualifier());
-            service.setAssertionAudiences(sp.getAssertionAudiences());
-            service.setServiceProviderNameIdQualifier(sp.getServiceProviderNameIdQualifier());
-
-            return service;
-        }
-
-        return null;
-    }
-
-    public static WAClientApp fromRegisteredService(final RegisteredService service) {
-        WAClientApp clientApp = new WAClientApp();
-
-        if (service.getAuthenticationPolicy() != null) {
-            DefaultAuthPolicyConf authPolicyConf = new DefaultAuthPolicyConf();
-            DefaultAuthPolicyCriteriaConf criteria = new DefaultAuthPolicyCriteriaConf();
-            criteria.setAll(((DefaultAuthPolicyCriteriaConf) service.getAuthenticationPolicy().getCriteria()).isAll());
-            authPolicyConf.setCriteria(criteria);
-
-            clientApp.setAuthPolicyConf(authPolicyConf);
-        }
-
-        if (service.getAccessStrategy() != null) {
-            DefaultAccessPolicyConf accessPolicyConf = new DefaultAccessPolicyConf();
-            accessPolicyConf.setEnabled(
-                    ((DefaultRegisteredServiceAccessStrategy) service.getAccessStrategy()).isEnabled());
-            accessPolicyConf.setSsoEnabled(
-                    ((DefaultRegisteredServiceAccessStrategy) service.getAccessStrategy()).isSsoEnabled());
-            accessPolicyConf.getRequiredAttributes().putAll(
-                    ((DefaultRegisteredServiceAccessStrategy) service.getAccessStrategy()).getRejectedAttributes());
-
-            clientApp.setAccessPolicyConf(accessPolicyConf);
-        }
-
-        if (service.getAttributeReleasePolicy() != null) {
-
-            if (service.getAttributeReleasePolicy() instanceof ReturnAllowedAttributeReleasePolicy) {
-                ReturnAllowedAttributeReleasePolicy returnAllowedAttributeReleasePolicy =
-                        ReturnAllowedAttributeReleasePolicy.class.cast(service.getAttributeReleasePolicy());
-                AllowedAttrReleasePolicyConf allowedAttrReleasePolicyConf = new AllowedAttrReleasePolicyConf();
-                allowedAttrReleasePolicyConf.getAllowedAttributes().addAll(returnAllowedAttributeReleasePolicy.
-                        getAllowedAttributes());
-
-                clientApp.setAttrReleasePolicyConf(allowedAttrReleasePolicyConf);
-            }
-        }
-
-        if (service instanceof OidcRegisteredService) {
-            OidcRegisteredService oidc = OidcRegisteredService.class.cast(service);
-            OIDCRPTO oidcrpto = new OIDCRPTO();
-
-            oidcrpto.getRedirectUris().addAll(Arrays.asList(oidc.getServiceId().split("|")));
-            oidcrpto.setName(oidc.getName());
-            oidcrpto.setDescription(oidc.getDescription());
-            oidcrpto.setClientId(oidc.getClientId());
-            oidcrpto.setClientSecret(oidc.getClientSecret());
-            oidcrpto.setSignIdToken(oidc.isSignIdToken());
-            oidcrpto.setJwks(oidc.getJwks());
-            oidcrpto.setSubjectType(OIDCSubjectType.valueOf(oidc.getSubjectType()));
-            oidcrpto.getSupportedGrantTypes().addAll(oidc.getSupportedGrantTypes());
-            oidcrpto.getSupportedResponseTypes().addAll(oidc.getSupportedResponseTypes());
-
-            clientApp.setClientAppTO(oidcrpto);
-        } else if (service instanceof SamlRegisteredService) {
-            SamlRegisteredService saml = SamlRegisteredService.class.cast(service);
-            SAML2SPTO saml2spto = new SAML2SPTO();
-
-            saml2spto.setEntityId(saml.getServiceId());
-            saml2spto.setName(saml.getName());
-            saml2spto.setDescription(saml.getDescription());
-
-            saml2spto.setMetadataLocation(saml.getMetadataLocation());
-            saml2spto.setMetadataSignatureLocation(saml.getMetadataSignatureLocation());
-            saml2spto.setSignAssertions(saml.isSignAssertions());
-            saml2spto.setSignResponses(saml.isSignResponses());
-            saml2spto.setEncryptionOptional(saml.isEncryptionOptional());
-            saml2spto.setEncryptAssertions(saml.isEncryptAssertions());
-            saml2spto.setRequiredAuthenticationContextClass(saml.getRequiredAuthenticationContextClass());
-            saml2spto.setRequiredNameIdFormat(SAML2SPNameId.valueOf(saml.getRequiredNameIdFormat()));
-            saml2spto.setSkewAllowance(saml.getSkewAllowance());
-            saml2spto.setNameIdQualifier(saml.getNameIdQualifier());
-            saml2spto.setAssertionAudiences(saml.getAssertionAudiences());
-            saml2spto.setServiceProviderNameIdQualifier(saml.getServiceProviderNameIdQualifier());
-
-            clientApp.setClientAppTO(saml2spto);
-        }
-
-        return clientApp;
-    }
-}
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeServiceRegistry.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeServiceRegistry.java
index 1eddd9f..a10a7ff 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeServiceRegistry.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeServiceRegistry.java
@@ -18,11 +18,12 @@
  */
 package org.apache.syncope.wa.starter;
 
+import org.apache.syncope.wa.starter.mapping.RegisteredServiceMapper;
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.common.lib.types.ClientAppType;
-import org.apache.syncope.wa.WARestClient;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.services.AbstractServiceRegistry;
 import org.apereo.cas.services.OidcRegisteredService;
 import org.apereo.cas.services.RegisteredService;
@@ -39,13 +40,17 @@ public class SyncopeServiceRegistry extends AbstractServiceRegistry {
 
     private final WARestClient restClient;
 
+    private final RegisteredServiceMapper registeredServiceMapper;
+
     public SyncopeServiceRegistry(
             final WARestClient restClient,
+            final RegisteredServiceMapper registeredServiceMapper,
             final ConfigurableApplicationContext applicationContext,
             final Collection<ServiceRegistryListener> serviceRegistryListeners) {
 
         super(applicationContext, serviceRegistryListeners);
         this.restClient = restClient;
+        this.registeredServiceMapper = registeredServiceMapper;
     }
 
     @Override
@@ -63,7 +68,7 @@ public class SyncopeServiceRegistry extends AbstractServiceRegistry {
         if (WARestClient.isReady()) {
             LOG.info("Loading application definitions");
             return restClient.getSyncopeClient().getService(WAClientAppService.class).list().stream().
-                    map(clientApp -> RegisteredServiceMapper.toRegisteredService(clientApp)).
+                    map(clientApp -> registeredServiceMapper.toRegisteredService(clientApp)).
                     collect(Collectors.toList());
         }
         LOG.debug("Syncope client is not yet ready to fetch application definitions");
@@ -74,7 +79,7 @@ public class SyncopeServiceRegistry extends AbstractServiceRegistry {
     public RegisteredService findServiceById(final long id) {
         if (WARestClient.isReady()) {
             LOG.info("Searching for application definition by id {}", id);
-            return RegisteredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
+            return registeredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
                     getService(WAClientAppService.class).read(id, null));
         }
         LOG.debug("Syncope client is not yet ready to fetch application definitions");
@@ -87,10 +92,10 @@ public class SyncopeServiceRegistry extends AbstractServiceRegistry {
         if (WARestClient.isReady()) {
             LOG.info("Searching for application definition by id {} and type {}", id, clazz);
             if (clazz.isInstance(OidcRegisteredService.class)) {
-                return (T) RegisteredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
+                return (T) registeredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
                         getService(WAClientAppService.class).read(id, ClientAppType.OIDCRP));
             } else if (clazz.isInstance(SamlRegisteredService.class)) {
-                return (T) RegisteredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
+                return (T) registeredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
                         getService(WAClientAppService.class).read(id, ClientAppType.SAML2SP));
             }
         }
@@ -104,10 +109,10 @@ public class SyncopeServiceRegistry extends AbstractServiceRegistry {
         if (WARestClient.isReady()) {
             LOG.info("Searching for application definition by name {} and type {}", name, clazz);
             if (clazz.isInstance(OidcRegisteredService.class)) {
-                return (T) RegisteredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
+                return (T) registeredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
                         getService(WAClientAppService.class).read(name, ClientAppType.OIDCRP));
             } else if (clazz.isInstance(SamlRegisteredService.class)) {
-                return (T) RegisteredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
+                return (T) registeredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
                         getService(WAClientAppService.class).read(name, ClientAppType.SAML2SP));
             }
         }
@@ -119,7 +124,7 @@ public class SyncopeServiceRegistry extends AbstractServiceRegistry {
     public RegisteredService findServiceByExactServiceName(final String name) {
         if (WARestClient.isReady()) {
             LOG.info("Searching for application definition by name {}", name);
-            return RegisteredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
+            return registeredServiceMapper.toRegisteredService(restClient.getSyncopeClient().
                     getService(WAClientAppService.class).read(name, null));
         }
         LOG.debug("Syncope client is not yet ready to fetch application definitions");
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAAuditTrailManager.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAAuditTrailManager.java
index 7dbd561..731eadd 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAAuditTrailManager.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAAuditTrailManager.java
@@ -27,7 +27,7 @@ import org.apache.syncope.common.lib.log.AuditEntry;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.rest.api.service.LoggerService;
-import org.apache.syncope.wa.WARestClient;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.inspektr.audit.AuditActionContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAConfiguration.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAConfiguration.java
index 9ff7c55..6a615cc 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAConfiguration.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAConfiguration.java
@@ -18,37 +18,46 @@
  */
 package org.apache.syncope.wa.starter;
 
-import org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer;
-import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer;
-import org.apereo.cas.services.ServiceRegistryListener;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
 import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStart;
 import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStop;
-import org.apache.syncope.wa.WARestClient;
+import org.apache.syncope.wa.bootstrap.WARestClient;
+import org.apache.syncope.wa.starter.mapping.AccessMapFor;
+import org.apache.syncope.wa.starter.mapping.AccessMapper;
+import org.apache.syncope.wa.starter.mapping.AttrReleaseMapFor;
+import org.apache.syncope.wa.starter.mapping.AttrReleaseMapper;
+import org.apache.syncope.wa.starter.mapping.AuthMapFor;
+import org.apache.syncope.wa.starter.mapping.AuthMapper;
+import org.apache.syncope.wa.starter.mapping.ClientAppMapFor;
+import org.apache.syncope.wa.starter.mapping.ClientAppMapper;
+import org.apache.syncope.wa.starter.mapping.RegisteredServiceMapper;
+import org.apache.syncope.wa.starter.saml.idp.metadata.RestfulSamlIdPMetadataGenerator;
+import org.apache.syncope.wa.starter.saml.idp.metadata.RestfulSamlIdPMetadataLocator;
+import org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer;
+import org.apereo.cas.configuration.CasConfigurationProperties;
+import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer;
+import org.apereo.cas.services.ServiceRegistryListener;
 import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGenerator;
+import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGeneratorConfigurationContext;
 import org.apereo.cas.support.saml.idp.metadata.locator.SamlIdPMetadataLocator;
+import org.apereo.cas.support.saml.idp.metadata.writer.SamlIdPCertificateAndKeyWriter;
+import org.apereo.cas.util.crypto.CipherExecutor;
+import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import java.util.Collection;
-import org.apache.syncope.wa.saml.idp.metadata.RestfulSamlIdPMetadataGenerator;
-import org.apache.syncope.wa.saml.idp.metadata.RestfulSamlIdPMetadataLocator;
-import org.apereo.cas.configuration.CasConfigurationProperties;
-import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGeneratorConfigurationContext;
-import org.apereo.cas.support.saml.idp.metadata.writer.SamlIdPCertificateAndKeyWriter;
-import org.apereo.cas.util.crypto.CipherExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.core.io.ResourceLoader;
 
 @Configuration
 public class SyncopeWAConfiguration {
 
-    private static final Logger LOG = LoggerFactory.getLogger(SyncopeWAConfiguration.class);
-
     @Autowired
     private CasConfigurationProperties casProperties;
 
@@ -67,10 +76,68 @@ public class SyncopeWAConfiguration {
     private Collection<ServiceRegistryListener> serviceRegistryListeners;
 
     @Autowired
+    private ApplicationContext ctx;
+
+    @ConditionalOnMissingBean
     @Bean
-    public ServiceRegistryExecutionPlanConfigurer syncopeServiceRegistryConfigurer(final WARestClient restClient) {
-        SyncopeServiceRegistry registry =
-                new SyncopeServiceRegistry(restClient, applicationContext, serviceRegistryListeners);
+    public RegisteredServiceMapper registeredServiceMapper() {
+        Map<String, AuthMapper> authPolicyConfMappers = new HashMap<>();
+        Map<String, AuthMapper> registeredServiceAuthenticationPolicyMappers = new HashMap<>();
+        ctx.getBeansOfType(AuthMapper.class).forEach((name, bean) -> {
+            AuthMapFor authMapFor = ctx.findAnnotationOnBean(name, AuthMapFor.class);
+            if (authMapFor != null) {
+                authPolicyConfMappers.put(authMapFor.authPolicyConfClass().getName(), bean);
+                registeredServiceAuthenticationPolicyMappers.put(
+                        authMapFor.registeredServiceAuthenticationPolicyClass().getName(), bean);
+            }
+        });
+
+        Map<String, AccessMapper> accessPolicyConfMappers = new HashMap<>();
+        Map<String, AccessMapper> registeredServiceAccessStrategyMappers = new HashMap<>();
+        ctx.getBeansOfType(AccessMapper.class).forEach((name, bean) -> {
+            AccessMapFor accessMapFor = ctx.findAnnotationOnBean(name, AccessMapFor.class);
+            if (accessMapFor != null) {
+                accessPolicyConfMappers.put(accessMapFor.accessPolicyConfClass().getName(), bean);
+                registeredServiceAccessStrategyMappers.put(
+                        accessMapFor.registeredServiceAccessStrategyClass().getName(), bean);
+            }
+        });
+
+        Map<String, AttrReleaseMapper> attrReleasePolicyConfMappers = new HashMap<>();
+        Map<String, AttrReleaseMapper> registeredServiceAttributeReleasePolicyMappers = new HashMap<>();
+        ctx.getBeansOfType(AttrReleaseMapper.class).forEach((name, bean) -> {
+            AttrReleaseMapFor attrReleaseMapFor = ctx.findAnnotationOnBean(name, AttrReleaseMapFor.class);
+            if (attrReleaseMapFor != null) {
+                attrReleasePolicyConfMappers.put(attrReleaseMapFor.attrReleasePolicyConfClass().getName(), bean);
+                registeredServiceAttributeReleasePolicyMappers.put(
+                        attrReleaseMapFor.registeredServiceAttributeReleasePolicyClass().getName(), bean);
+            }
+        });
+
+        Map<String, ClientAppMapper> clientAppTOMappers = new HashMap<>();
+        Map<String, ClientAppMapper> registeredServiceMappers = new HashMap<>();
+        ctx.getBeansOfType(ClientAppMapper.class).forEach((name, bean) -> {
+            ClientAppMapFor clientAppMapFor = ctx.findAnnotationOnBean(name, ClientAppMapFor.class);
+            if (clientAppMapFor != null) {
+                clientAppTOMappers.put(clientAppMapFor.clientAppClass().getName(), bean);
+                registeredServiceMappers.put(clientAppMapFor.registeredServiceClass().getName(), bean);
+            }
+        });
+
+        return new RegisteredServiceMapper(
+                authPolicyConfMappers, registeredServiceAuthenticationPolicyMappers,
+                accessPolicyConfMappers, registeredServiceAccessStrategyMappers,
+                attrReleasePolicyConfMappers, registeredServiceAttributeReleasePolicyMappers,
+                clientAppTOMappers, registeredServiceMappers);
+    }
+
+    @Autowired
+    @Bean
+    public ServiceRegistryExecutionPlanConfigurer syncopeServiceRegistryConfigurer(
+            final WARestClient restClient, final RegisteredServiceMapper registeredServiceMapper) {
+
+        SyncopeServiceRegistry registry = new SyncopeServiceRegistry(
+                restClient, registeredServiceMapper, applicationContext, serviceRegistryListeners);
         return plan -> plan.registerServiceRegistry(registry);
     }
 
@@ -109,5 +176,4 @@ public class SyncopeWAConfiguration {
     public KeymasterStop keymasterStop() {
         return new KeymasterStop(NetworkService.Type.WA);
     }
-
 }
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWARefreshContextJob.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWARefreshContextJob.java
index 8b3bae3..9d5a1cc 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWARefreshContextJob.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWARefreshContextJob.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.wa.starter;
 
-import org.apache.syncope.wa.WARestClient;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGenerator;
 import org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument;
 import org.quartz.Job;
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AccessMapFor.java
similarity index 58%
copy from common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AccessMapFor.java
index 8bcb84b..72626b4 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AccessMapFor.java
@@ -16,24 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.policy;
+package org.apache.syncope.wa.starter.mapping;
 
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.syncope.common.lib.policy.AccessPolicyConf;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
 
-@XmlRootElement(name = "AnyAuthPolicyCriteriaConf")
-@XmlType
-public class DefaultAuthPolicyCriteriaConf extends AbstractAuthPolicyCriteriaConf {
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AccessMapFor {
 
-    private static final long serialVersionUID = 3928807032588105869L;
+    Class<? extends AccessPolicyConf> accessPolicyConfClass();
 
-    private boolean all;
-
-    public boolean isAll() {
-        return all;
-    }
-
-    public void setAll(final boolean all) {
-        this.all = all;
-    }
+    Class<? extends RegisteredServiceAccessStrategy> registeredServiceAccessStrategyClass();
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AccessMapper.java
similarity index 70%
copy from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AccessMapper.java
index d7c4a9a..7ef07ff 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AccessMapper.java
@@ -16,19 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.persistence.api.entity.policy;
+package org.apache.syncope.wa.starter.mapping;
 
+import org.apache.syncope.common.lib.policy.AccessPolicyConf;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
 
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+public interface AccessMapper {
 
-public interface AuthPolicy extends Policy {
-
-    String getName();
-
-    void setName(String name);
-
-    Implementation getConfiguration();
-
-    void setConfiguration(Implementation configuration);
+    RegisteredServiceAccessStrategy build(AccessPolicyConf conf);
 
+    AccessPolicyConf build(RegisteredServiceAccessStrategy strategy);
 }
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AllowedAttrReleaseMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AllowedAttrReleaseMapper.java
new file mode 100644
index 0000000..9908f51
--- /dev/null
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AllowedAttrReleaseMapper.java
@@ -0,0 +1,54 @@
+/*
+ * 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.wa.starter.mapping;
+
+import org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
+import org.apereo.cas.services.DenyAllAttributeReleasePolicy;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy;
+import org.springframework.stereotype.Component;
+
+@AttrReleaseMapFor(
+        attrReleasePolicyConfClass = AllowedAttrReleasePolicyConf.class,
+        registeredServiceAttributeReleasePolicyClass = ReturnAllowedAttributeReleasePolicy.class)
+@Component
+public class AllowedAttrReleaseMapper implements AttrReleaseMapper {
+
+    @Override
+    public RegisteredServiceAttributeReleasePolicy build(final AttrReleasePolicyConf conf) {
+        RegisteredServiceAttributeReleasePolicy attributeReleasePolicy;
+        if (!((AllowedAttrReleasePolicyConf) conf).getAllowedAttrs().isEmpty()) {
+            attributeReleasePolicy = new ReturnAllowedAttributeReleasePolicy();
+            ((ReturnAllowedAttributeReleasePolicy) attributeReleasePolicy).getAllowedAttributes().addAll(
+                    ((AllowedAttrReleasePolicyConf) conf).getAllowedAttrs());
+        } else {
+            attributeReleasePolicy = new DenyAllAttributeReleasePolicy();
+        }
+
+        return attributeReleasePolicy;
+    }
+
+    @Override
+    public AttrReleasePolicyConf build(final RegisteredServiceAttributeReleasePolicy policy) {
+        AllowedAttrReleasePolicyConf conf = new AllowedAttrReleasePolicyConf();
+        conf.getAllowedAttrs().addAll(((ReturnAllowedAttributeReleasePolicy) policy).getAllowedAttributes());
+        return conf;
+    }
+}
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapFor.java
similarity index 56%
copy from common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapFor.java
index 8bcb84b..2060fea 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapFor.java
@@ -16,24 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.policy;
+package org.apache.syncope.wa.starter.mapping;
 
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
 
-@XmlRootElement(name = "AnyAuthPolicyCriteriaConf")
-@XmlType
-public class DefaultAuthPolicyCriteriaConf extends AbstractAuthPolicyCriteriaConf {
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AttrReleaseMapFor {
 
-    private static final long serialVersionUID = 3928807032588105869L;
+    Class<? extends AttrReleasePolicyConf> attrReleasePolicyConfClass();
 
-    private boolean all;
-
-    public boolean isAll() {
-        return all;
-    }
-
-    public void setAll(final boolean all) {
-        this.all = all;
-    }
+    Class<? extends RegisteredServiceAttributeReleasePolicy> registeredServiceAttributeReleasePolicyClass();
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapper.java
similarity index 68%
copy from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapper.java
index d7c4a9a..50dd5bd 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapper.java
@@ -16,19 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.persistence.api.entity.policy;
+package org.apache.syncope.wa.starter.mapping;
 
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
 
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+public interface AttrReleaseMapper {
 
-public interface AuthPolicy extends Policy {
-
-    String getName();
-
-    void setName(String name);
-
-    Implementation getConfiguration();
-
-    void setConfiguration(Implementation configuration);
+    RegisteredServiceAttributeReleasePolicy build(AttrReleasePolicyConf conf);
 
+    AttrReleasePolicyConf build(RegisteredServiceAttributeReleasePolicy policy);
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapFor.java
similarity index 57%
copy from common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapFor.java
index 8bcb84b..95c9baf 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapFor.java
@@ -16,24 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.policy;
+package org.apache.syncope.wa.starter.mapping;
 
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.syncope.common.lib.policy.AuthPolicyConf;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
 
-@XmlRootElement(name = "AnyAuthPolicyCriteriaConf")
-@XmlType
-public class DefaultAuthPolicyCriteriaConf extends AbstractAuthPolicyCriteriaConf {
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AuthMapFor {
 
-    private static final long serialVersionUID = 3928807032588105869L;
+    Class<? extends AuthPolicyConf> authPolicyConfClass();
 
-    private boolean all;
-
-    public boolean isAll() {
-        return all;
-    }
-
-    public void setAll(final boolean all) {
-        this.all = all;
-    }
+    Class<? extends RegisteredServiceAuthenticationPolicy> registeredServiceAuthenticationPolicyClass();
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java
similarity index 69%
copy from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java
index d7c4a9a..dacb020 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java
@@ -16,19 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.persistence.api.entity.policy;
+package org.apache.syncope.wa.starter.mapping;
 
+import org.apache.syncope.common.lib.policy.AuthPolicyConf;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
 
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+public interface AuthMapper {
 
-public interface AuthPolicy extends Policy {
-
-    String getName();
-
-    void setName(String name);
-
-    Implementation getConfiguration();
-
-    void setConfiguration(Implementation configuration);
+    RegisteredServiceAuthenticationPolicy build(AuthPolicyConf conf);
 
+    AuthPolicyConf build(RegisteredServiceAuthenticationPolicy policy);
 }
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapFor.java
similarity index 60%
copy from common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
copy to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapFor.java
index 8bcb84b..f4526ad 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapFor.java
@@ -16,24 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.policy;
+package org.apache.syncope.wa.starter.mapping;
 
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.syncope.common.lib.to.client.ClientAppTO;
+import org.apereo.cas.services.RegisteredService;
 
-@XmlRootElement(name = "AnyAuthPolicyCriteriaConf")
-@XmlType
-public class DefaultAuthPolicyCriteriaConf extends AbstractAuthPolicyCriteriaConf {
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ClientAppMapFor {
 
-    private static final long serialVersionUID = 3928807032588105869L;
+    Class<? extends ClientAppTO> clientAppClass();
 
-    private boolean all;
-
-    public boolean isAll() {
-        return all;
-    }
-
-    public void setAll(final boolean all) {
-        this.all = all;
-    }
+    Class<? extends RegisteredService> registeredServiceClass();
 }
diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/init/AMImplementationTypeLoader.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
similarity index 53%
rename from core/am/logic/src/main/java/org/apache/syncope/core/logic/init/AMImplementationTypeLoader.java
rename to wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
index da5d393..4041eff 100644
--- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/init/AMImplementationTypeLoader.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
@@ -16,24 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.logic.init;
+package org.apache.syncope.wa.starter.mapping;
 
-import org.apache.syncope.common.lib.types.AMImplementationType;
-import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
-import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.springframework.core.Ordered;
-import org.springframework.stereotype.Component;
+import org.apache.syncope.common.lib.to.client.ClientAppTO;
+import org.apereo.cas.services.RegisteredService;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
 
-@Component
-public class AMImplementationTypeLoader implements SyncopeCoreLoader {
+public interface ClientAppMapper {
 
-    @Override
-    public int getOrder() {
-        return Ordered.HIGHEST_PRECEDENCE;
-    }
+    RegisteredService build(
+            ClientAppTO clientAppTO,
+            RegisteredServiceAuthenticationPolicy authPolicy,
+            RegisteredServiceAccessStrategy accessStrategy,
+            RegisteredServiceAttributeReleasePolicy attributeReleasePolicy);
 
-    @Override
-    public void load() {
-        ImplementationTypesHolder.getInstance().putAll(AMImplementationType.values());
-    }
+    ClientAppTO buid(RegisteredService service);
 }
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.java
new file mode 100644
index 0000000..9c44199
--- /dev/null
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.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.wa.starter.mapping;
+
+import org.apache.syncope.common.lib.policy.AccessPolicyConf;
+import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
+import org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
+import org.springframework.stereotype.Component;
+
+@AccessMapFor(
+        accessPolicyConfClass = DefaultAccessPolicyConf.class,
+        registeredServiceAccessStrategyClass = DefaultRegisteredServiceAccessStrategy.class)
+@Component
+public class DefaultAccessMapper implements AccessMapper {
+
+    @Override
+    public RegisteredServiceAccessStrategy build(final AccessPolicyConf conf) {
+        RegisteredServiceAccessStrategy accessStrategy =
+                new DefaultRegisteredServiceAccessStrategy(conf.isEnabled(), conf.isSsoEnabled());
+        accessStrategy.getRequiredAttributes().putAll(conf.getRequiredAttrs());
+        return accessStrategy;
+    }
+
+    @Override
+    public AccessPolicyConf build(final RegisteredServiceAccessStrategy strategy) {
+        DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
+        conf.setEnabled(((DefaultRegisteredServiceAccessStrategy) strategy).isEnabled());
+        conf.setSsoEnabled(((DefaultRegisteredServiceAccessStrategy) strategy).isSsoEnabled());
+        conf.getRequiredAttrs().putAll(((DefaultRegisteredServiceAccessStrategy) strategy).getRejectedAttributes());
+        return conf;
+    }
+}
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java
new file mode 100644
index 0000000..95c2f7e
--- /dev/null
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java
@@ -0,0 +1,53 @@
+/*
+ * 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.wa.starter.mapping;
+
+import org.apache.syncope.common.lib.policy.AuthPolicyConf;
+import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
+import org.apache.syncope.common.lib.policy.DefaultAuthPolicyCriteriaConf;
+import org.apereo.cas.services.AnyAuthenticationHandlerRegisteredServiceAuthenticationPolicyCriteria;
+import org.apereo.cas.services.DefaultRegisteredServiceAuthenticationPolicy;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
+import org.springframework.stereotype.Component;
+
+@AuthMapFor(
+        authPolicyConfClass = DefaultAuthPolicyConf.class,
+        registeredServiceAuthenticationPolicyClass = DefaultRegisteredServiceAuthenticationPolicy.class)
+@Component
+public class DefaultAuthMapper implements AuthMapper {
+
+    @Override
+    public RegisteredServiceAuthenticationPolicy build(final AuthPolicyConf conf) {
+        DefaultRegisteredServiceAuthenticationPolicy authPolicy = new DefaultRegisteredServiceAuthenticationPolicy();
+        AnyAuthenticationHandlerRegisteredServiceAuthenticationPolicyCriteria criteria =
+                new AnyAuthenticationHandlerRegisteredServiceAuthenticationPolicyCriteria();
+        criteria.setTryAll(((DefaultAuthPolicyCriteriaConf) conf.getCriteria()).isAll());
+        authPolicy.setCriteria(criteria);
+        return authPolicy;
+    }
+
+    @Override
+    public AuthPolicyConf build(final RegisteredServiceAuthenticationPolicy policy) {
+        DefaultAuthPolicyConf conf = new DefaultAuthPolicyConf();
+        DefaultAuthPolicyCriteriaConf criteria = new DefaultAuthPolicyCriteriaConf();
+        criteria.setAll(((DefaultAuthPolicyCriteriaConf) policy.getCriteria()).isAll());
+        conf.setCriteria(criteria);
+        return conf;
+    }
+}
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPTOMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPTOMapper.java
new file mode 100644
index 0000000..850e9d7
--- /dev/null
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPTOMapper.java
@@ -0,0 +1,86 @@
+/*
+ * 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.wa.starter.mapping;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import org.apache.syncope.common.lib.to.client.ClientAppTO;
+import org.apache.syncope.common.lib.to.client.OIDCRPTO;
+import org.apache.syncope.common.lib.types.OIDCSubjectType;
+import org.apereo.cas.services.OidcRegisteredService;
+import org.apereo.cas.services.RegisteredService;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
+import org.springframework.stereotype.Component;
+
+@ClientAppMapFor(clientAppClass = OIDCRPTO.class, registeredServiceClass = OidcRegisteredService.class)
+@Component
+public class OIDCRPTOMapper implements ClientAppMapper {
+
+    @Override
+    public RegisteredService build(
+            final ClientAppTO clientAppTO,
+            final RegisteredServiceAuthenticationPolicy authPolicy,
+            final RegisteredServiceAccessStrategy accessStrategy,
+            final RegisteredServiceAttributeReleasePolicy attributeReleasePolicy) {
+
+        OIDCRPTO rp = OIDCRPTO.class.cast(clientAppTO);
+
+        OidcRegisteredService service = new OidcRegisteredService();
+
+        String redirectURIs = String.join("|", rp.getRedirectUris());
+        service.setServiceId(redirectURIs);
+        service.setName(rp.getName());
+        service.setDescription(rp.getDescription());
+        service.setAccessStrategy(accessStrategy);
+        service.setAuthenticationPolicy(authPolicy);
+        service.setAttributeReleasePolicy(attributeReleasePolicy);
+
+        service.setClientId(rp.getClientId());
+        service.setClientSecret(rp.getClientSecret());
+        service.setSignIdToken(rp.isSignIdToken());
+        service.setJwks(rp.getJwks());
+        service.setSubjectType(rp.getSubjectType().name());
+        service.setRedirectUrl(redirectURIs);
+        service.setSupportedGrantTypes((HashSet<String>) rp.getSupportedGrantTypes());
+        service.setSupportedResponseTypes((HashSet<String>) rp.getSupportedResponseTypes());
+
+        return service;
+    }
+
+    public ClientAppTO buid(final RegisteredService service) {
+        OidcRegisteredService oidc = OidcRegisteredService.class.cast(service);
+
+        OIDCRPTO oidcrpto = new OIDCRPTO();
+
+        oidcrpto.getRedirectUris().addAll(Arrays.asList(oidc.getServiceId().split("|")));
+        oidcrpto.setName(oidc.getName());
+        oidcrpto.setDescription(oidc.getDescription());
+        oidcrpto.setClientId(oidc.getClientId());
+        oidcrpto.setClientSecret(oidc.getClientSecret());
+        oidcrpto.setSignIdToken(oidc.isSignIdToken());
+        oidcrpto.setJwks(oidc.getJwks());
+        oidcrpto.setSubjectType(OIDCSubjectType.valueOf(oidc.getSubjectType()));
+        oidcrpto.getSupportedGrantTypes().addAll(oidc.getSupportedGrantTypes());
+        oidcrpto.getSupportedResponseTypes().addAll(oidc.getSupportedResponseTypes());
+
+        return oidcrpto;
+    }
+}
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java
new file mode 100644
index 0000000..8b6bc65
--- /dev/null
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java
@@ -0,0 +1,131 @@
+/*
+ * 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.wa.starter.mapping;
+
+import java.util.Map;
+import java.util.Optional;
+import org.apache.syncope.common.lib.wa.WAClientApp;
+import org.apereo.cas.services.RegisteredService;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RegisteredServiceMapper {
+
+    protected final Map<String, AuthMapper> authPolicyConfMappers;
+
+    protected final Map<String, AuthMapper> registeredServiceAuthenticationPolicyMappers;
+
+    protected final Map<String, AccessMapper> accessPolicyConfMappers;
+
+    protected final Map<String, AccessMapper> registeredServiceAccessStrategyMappers;
+
+    protected final Map<String, AttrReleaseMapper> attrReleasePolicyConfMappers;
+
+    protected final Map<String, AttrReleaseMapper> registeredServiceAttributeReleasePolicyMappers;
+
+    protected final Map<String, ClientAppMapper> clientAppTOMappers;
+
+    protected final Map<String, ClientAppMapper> registeredServiceMappers;
+
+    public RegisteredServiceMapper(
+            final Map<String, AuthMapper> authPolicyConfMappers,
+            final Map<String, AuthMapper> registeredServiceAuthenticationPolicyMappers,
+            final Map<String, AccessMapper> accessPolicyConfMappers,
+            final Map<String, AccessMapper> registeredServiceAccessStrategyMappers,
+            final Map<String, AttrReleaseMapper> attrReleasePolicyConfMappers,
+            final Map<String, AttrReleaseMapper> registeredServiceAttributeReleasePolicyMappers,
+            final Map<String, ClientAppMapper> clientAppTOMappers,
+            final Map<String, ClientAppMapper> registeredServiceMappers) {
+
+        this.authPolicyConfMappers = authPolicyConfMappers;
+        this.registeredServiceAuthenticationPolicyMappers = registeredServiceAuthenticationPolicyMappers;
+        this.accessPolicyConfMappers = accessPolicyConfMappers;
+        this.registeredServiceAccessStrategyMappers = registeredServiceAccessStrategyMappers;
+        this.attrReleasePolicyConfMappers = attrReleasePolicyConfMappers;
+        this.registeredServiceAttributeReleasePolicyMappers = registeredServiceAttributeReleasePolicyMappers;
+        this.clientAppTOMappers = clientAppTOMappers;
+        this.registeredServiceMappers = registeredServiceMappers;
+    }
+
+    public RegisteredService toRegisteredService(final WAClientApp clientApp) {
+        RegisteredServiceAuthenticationPolicy authPolicy = null;
+        if (clientApp.getAuthPolicyConf() != null) {
+            AuthMapper authMapper =
+                    authPolicyConfMappers.get(clientApp.getAuthPolicyConf().getClass().getName());
+            authPolicy = Optional.ofNullable(authMapper).
+                    map(mapper -> mapper.build(clientApp.getAuthPolicyConf())).orElse(null);
+        }
+
+        RegisteredServiceAccessStrategy accessStrategy = null;
+        if (clientApp.getAccessPolicyConf() != null) {
+            AccessMapper accessPolicyConfMapper =
+                    accessPolicyConfMappers.get(clientApp.getAccessPolicyConf().getClass().getName());
+            accessStrategy = Optional.ofNullable(accessPolicyConfMapper).
+                    map(mapper -> mapper.build(clientApp.getAccessPolicyConf())).orElse(null);
+        }
+
+        RegisteredServiceAttributeReleasePolicy attributeReleasePolicy = null;
+        if (clientApp.getAttrReleasePolicyConf() != null) {
+            AttrReleaseMapper attrReleasePolicyConfMapper =
+                    attrReleasePolicyConfMappers.get(clientApp.getAttrReleasePolicyConf().getClass().getName());
+            attributeReleasePolicy = Optional.ofNullable(attrReleasePolicyConfMapper).
+                    map(mapper -> mapper.build(clientApp.getAttrReleasePolicyConf())).orElse(null);
+        }
+
+        ClientAppMapper clientAppMapper = clientAppTOMappers.get(clientApp.getClientAppTO().getClass().getName());
+        if (clientAppMapper == null) {
+            return null;
+        }
+        return clientAppMapper.build(clientApp.getClientAppTO(), authPolicy, accessStrategy, attributeReleasePolicy);
+    }
+
+    public WAClientApp fromRegisteredService(final RegisteredService service) {
+        WAClientApp clientApp = new WAClientApp();
+
+        if (service.getAuthenticationPolicy() != null) {
+            AuthMapper authMapper = registeredServiceAuthenticationPolicyMappers.get(
+                    service.getAuthenticationPolicy().getClass().getName());
+            clientApp.setAuthPolicyConf(Optional.ofNullable(authMapper).
+                    map(mapper -> mapper.build(service.getAuthenticationPolicy())).orElse(null));
+        }
+
+        if (service.getAccessStrategy() != null) {
+            AccessMapper accessPolicyConfMapper = registeredServiceAccessStrategyMappers.get(
+                    service.getAccessStrategy().getClass().getName());
+            clientApp.setAccessPolicyConf(Optional.ofNullable(accessPolicyConfMapper).
+                    map(mapper -> mapper.build(service.getAccessStrategy())).orElse(null));
+        }
+
+        if (service.getAttributeReleasePolicy() != null) {
+            AttrReleaseMapper attrReleasePolicyConfMapper = registeredServiceAttributeReleasePolicyMappers.get(
+                    service.getAttributeReleasePolicy().getClass().getName());
+            clientApp.setAttrReleasePolicyConf(Optional.ofNullable(attrReleasePolicyConfMapper).
+                    map(mapper -> mapper.build(service.getAttributeReleasePolicy())).orElse(null));
+        }
+
+        ClientAppMapper clientAppMapper = registeredServiceMappers.get(service.getClass().getName());
+        clientApp.setClientAppTO(Optional.ofNullable(clientAppMapper).
+                map(mapper -> mapper.buid(service)).orElse(null));
+
+        return clientApp;
+    }
+}
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPTOMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPTOMapper.java
new file mode 100644
index 0000000..96df87d
--- /dev/null
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPTOMapper.java
@@ -0,0 +1,94 @@
+/*
+ * 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.wa.starter.mapping;
+
+import org.apache.syncope.common.lib.to.client.ClientAppTO;
+import org.apache.syncope.common.lib.to.client.SAML2SPTO;
+import org.apache.syncope.common.lib.types.SAML2SPNameId;
+import org.apereo.cas.services.RegisteredService;
+import org.apereo.cas.services.RegisteredServiceAccessStrategy;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.services.RegisteredServiceAuthenticationPolicy;
+import org.apereo.cas.support.saml.services.SamlRegisteredService;
+import org.springframework.stereotype.Component;
+
+@ClientAppMapFor(clientAppClass = SAML2SPTO.class, registeredServiceClass = SamlRegisteredService.class)
+@Component
+public class SAML2SPTOMapper implements ClientAppMapper {
+
+    @Override
+    public RegisteredService build(
+            final ClientAppTO clientAppTO,
+            final RegisteredServiceAuthenticationPolicy authPolicy,
+            final RegisteredServiceAccessStrategy accessStrategy,
+            final RegisteredServiceAttributeReleasePolicy attributeReleasePolicy) {
+
+        SAML2SPTO sp = SAML2SPTO.class.cast(clientAppTO);
+
+        SamlRegisteredService service = new SamlRegisteredService();
+
+        service.setServiceId(sp.getEntityId());
+        service.setName(sp.getName());
+        service.setDescription(sp.getDescription());
+        service.setAccessStrategy(accessStrategy);
+        service.setAuthenticationPolicy(authPolicy);
+        service.setAttributeReleasePolicy(attributeReleasePolicy);
+
+        service.setMetadataLocation(sp.getMetadataLocation());
+        service.setMetadataSignatureLocation(sp.getMetadataSignatureLocation());
+        service.setSignAssertions(sp.isSignAssertions());
+        service.setSignResponses(sp.isSignResponses());
+        service.setEncryptionOptional(sp.isEncryptionOptional());
+        service.setEncryptAssertions(sp.isEncryptAssertions());
+        service.setRequiredAuthenticationContextClass(sp.getRequiredAuthenticationContextClass());
+        service.setRequiredNameIdFormat(sp.getRequiredNameIdFormat().getNameId());
+        service.setSkewAllowance(sp.getSkewAllowance());
+        service.setNameIdQualifier(sp.getNameIdQualifier());
+        service.setAssertionAudiences(sp.getAssertionAudiences());
+        service.setServiceProviderNameIdQualifier(sp.getServiceProviderNameIdQualifier());
+
+        return service;
+    }
+
+    @Override
+    public ClientAppTO buid(final RegisteredService service) {
+        SamlRegisteredService saml = SamlRegisteredService.class.cast(service);
+
+        SAML2SPTO saml2spto = new SAML2SPTO();
+
+        saml2spto.setEntityId(saml.getServiceId());
+        saml2spto.setName(saml.getName());
+        saml2spto.setDescription(saml.getDescription());
+
+        saml2spto.setMetadataLocation(saml.getMetadataLocation());
+        saml2spto.setMetadataSignatureLocation(saml.getMetadataSignatureLocation());
+        saml2spto.setSignAssertions(saml.isSignAssertions());
+        saml2spto.setSignResponses(saml.isSignResponses());
+        saml2spto.setEncryptionOptional(saml.isEncryptionOptional());
+        saml2spto.setEncryptAssertions(saml.isEncryptAssertions());
+        saml2spto.setRequiredAuthenticationContextClass(saml.getRequiredAuthenticationContextClass());
+        saml2spto.setRequiredNameIdFormat(SAML2SPNameId.valueOf(saml.getRequiredNameIdFormat()));
+        saml2spto.setSkewAllowance(saml.getSkewAllowance());
+        saml2spto.setNameIdQualifier(saml.getNameIdQualifier());
+        saml2spto.setAssertionAudiences(saml.getAssertionAudiences());
+        saml2spto.setServiceProviderNameIdQualifier(saml.getServiceProviderNameIdQualifier());
+
+        return saml2spto;
+    }
+}
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
similarity index 97%
rename from wa/starter/src/main/java/org/apache/syncope/wa/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
rename to wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
index 74bcb04..ceeff87 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
@@ -16,13 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.saml.idp.metadata;
+package org.apache.syncope.wa.starter.saml.idp.metadata;
 
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.SAML2IdPMetadataTO;
 import org.apache.syncope.common.rest.api.service.SAML2IdPMetadataService;
-import org.apache.syncope.wa.WARestClient;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.support.saml.idp.metadata.generator.BaseSamlIdPMetadataGenerator;
 import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGeneratorConfigurationContext;
 import org.apereo.cas.support.saml.services.SamlRegisteredService;
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
similarity index 97%
rename from wa/starter/src/main/java/org/apache/syncope/wa/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
rename to wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
index 57592e5..d2a1634 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.saml.idp.metadata;
+package org.apache.syncope.wa.starter.saml.idp.metadata;
 
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.SAML2IdPMetadataTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.service.SAML2IdPMetadataService;
-import org.apache.syncope.wa.WARestClient;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.support.saml.idp.metadata.locator.AbstractSamlIdPMetadataLocator;
 import org.apereo.cas.support.saml.services.SamlRegisteredService;
 import org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument;