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/04/09 14:24:45 UTC

[syncope] 05/07: [SYNCOPE-160] Access, Auth and AttrRelease policies

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

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

commit 41571dea01668b1c13863ced2ee3799841fb23ef
Author: Matteo Alessandroni <sk...@apache.org>
AuthorDate: Thu Apr 9 13:43:15 2020 +0200

    [SYNCOPE-160] Access, Auth and AttrRelease policies
---
 .../lib/policy/AbstractAccessPolicyConf.java       |  87 ++++++
 .../lib/policy/AbstractAttrReleasePolicyConf.java} |  42 +--
 .../common/lib/policy/AbstractAuthPolicyConf.java  |  60 +++++
 .../policy/AbstractAuthPolicyCriteriaConf.java}    |  53 ++--
 .../common/lib/policy/AccessPolicyConf.java}       |  34 ++-
 .../lib/policy/AllowedAttrReleasePolicyConf.java   |  48 ++++
 .../common/lib/policy/AttrReleasePolicyConf.java}  |  28 +-
 .../syncope/common/lib/policy/AuthPolicyConf.java} |  32 ++-
 .../common/lib/policy/AuthPolicyCriteriaConf.java} |  37 ++-
 .../lib/policy/DefaultAccessPolicyConf.java}       |  27 +-
 .../common/lib/policy/DefaultAuthPolicyConf.java   |  43 +++
 .../lib/policy/DefaultAuthPolicyCriteriaConf.java} |  36 ++-
 .../syncope/common/lib/policy/package-info.java}   |  31 +--
 .../syncope/common/lib/to/AccessPolicyTO.java      |  53 ++++
 .../syncope/common/lib/to/AttrReleasePolicyTO.java |  52 ++++
 .../apache/syncope/common/lib/to/AuthPolicyTO.java |  53 ++++
 .../syncope/common/lib/types/PolicyType.java       |  12 +
 .../org/apache/syncope/core/logic/PolicyLogic.java |   3 +
 .../core/persistence/api/dao/PolicyDAO.java        |   9 +
 .../api/entity/policy/AccessPolicy.java            |  30 +--
 .../api/entity/policy/AttrReleasePolicy.java       |  29 +-
 .../persistence/api/entity/policy/AuthPolicy.java  |  37 +--
 .../core/persistence/jpa/dao/JPAPolicyDAO.java     |  75 +++++-
 .../jpa/entity/policy/JPAAccessPolicy.java         |  68 +++++
 .../jpa/entity/policy/JPAAttrReleasePolicy.java    |  68 +++++
 .../jpa/entity/policy/JPAAuthPolicy.java           |  68 +++++
 .../jpa/entity/policy/JPAPolicyUtils.java          |  13 +-
 .../jpa/entity/policy/JPAPolicyUtilsFactory.java   |  18 ++
 .../core/persistence/jpa/inner/PolicyTest.java     | 186 +++++++++++--
 .../core/persistence/jpa/outer/PolicyTest.java     | 122 +++++++++
 .../java/data/PolicyDataBinderImpl.java            |  90 ++++++-
 .../org/apache/syncope/fit/core/PolicyITCase.java  | 291 ++++++++++++++++++++-
 32 files changed, 1544 insertions(+), 291 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
new file mode 100644
index 0000000..653fe11
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAccessPolicyConf.java
@@ -0,0 +1,87 @@
+/*
+ * 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.policy;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
+
+@XmlType
+@XmlSeeAlso({ DefaultAccessPolicyConf.class })
+public abstract class AbstractAccessPolicyConf implements Serializable, AccessPolicyConf {
+
+    private static final long serialVersionUID = 1153200197344709778L;
+
+    private String name;
+
+    private boolean enabled = true;
+
+    private boolean ssoEnabled = true;
+
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    private final Map<String, Set<String>> requiredAttributes = new LinkedHashMap<>();
+
+    public AbstractAccessPolicyConf() {
+        setName(getClass().getName());
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(final boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @Override
+    public boolean isSsoEnabled() {
+        return this.ssoEnabled;
+    }
+
+    public void setSsoEnabled(final boolean ssoEnabled) {
+        this.ssoEnabled = ssoEnabled;
+    }
+
+    @XmlElementWrapper(name = "requiredAttributes")
+    @XmlElement(name = "requiredAttribute")
+    @JsonProperty("requiredAttributes")
+    @Override
+    public Map<String, Set<String>> getRequiredAttributes() {
+        return requiredAttributes;
+    }
+
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAttrReleasePolicyConf.java
similarity index 54%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAttrReleasePolicyConf.java
index ea429c2..e3a8206 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAttrReleasePolicyConf.java
@@ -16,28 +16,30 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import java.io.Serializable;
 
-@XmlEnum
-public enum PolicyType {
+@XmlType
+@XmlSeeAlso({ AllowedAttrReleasePolicyConf.class })
+public abstract class AbstractAttrReleasePolicyConf implements Serializable, AttrReleasePolicyConf {
 
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+    private static final long serialVersionUID = 1153200197344709778L;
 
+    private String name;
+
+    public AbstractAttrReleasePolicyConf() {
+        setName(getClass().getName());
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+
+    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/AbstractAuthPolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyConf.java
new file mode 100644
index 0000000..ac19f37
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyConf.java
@@ -0,0 +1,60 @@
+/*
+ * 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.policy;
+
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import java.io.Serializable;
+
+@XmlType
+@XmlSeeAlso({ DefaultAuthPolicyConf.class })
+public abstract class AbstractAuthPolicyConf implements Serializable, AuthPolicyConf {
+
+    private static final long serialVersionUID = 9185127128182430142L;
+
+    private String name;
+
+    private AuthPolicyCriteriaConf criteria;
+
+    public AbstractAuthPolicyConf() {
+        setName(getClass().getName());
+    }
+
+    public AbstractAuthPolicyConf(final String name) {
+        setName(name);
+    }
+
+    @Override
+    public AuthPolicyCriteriaConf getCriteria() {
+        return criteria;
+    }
+
+    public void setCriteria(final AuthPolicyCriteriaConf criteria) {
+        this.criteria = criteria;
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(final String name) {
+        this.name = name;
+    }
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java
similarity index 51%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java
index ea429c2..1f497de 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AbstractAuthPolicyCriteriaConf.java
@@ -16,28 +16,35 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
-
-import javax.xml.bind.annotation.XmlEnum;
-
-@XmlEnum
-public enum PolicyType {
-
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+package org.apache.syncope.common.lib.policy;
+
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import java.io.Serializable;
+
+@XmlType
+@XmlSeeAlso({ DefaultAuthPolicyCriteriaConf.class })
+public abstract class AbstractAuthPolicyCriteriaConf implements AuthPolicyCriteriaConf, Serializable {
+
+    private static final long serialVersionUID = -6882164291962510245L;
+
+    private String name;
+
+    public AbstractAuthPolicyCriteriaConf() {
+        setName(getClass().getName());
+    }
+
+    public AbstractAuthPolicyCriteriaConf(final String name) {
+        setName(name);
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(final String name) {
+        this.name = name;
+    }
 
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java
similarity index 60%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java
index ea429c2..3cb0505 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AccessPolicyConf.java
@@ -16,28 +16,26 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
 
-@XmlEnum
-public enum PolicyType {
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+public interface AccessPolicyConf extends Serializable {
 
     /**
-     * How username values should look like.
+     * Give name of related access policy.
+     *
+     * @return name of this access policy
      */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+    String getName();
+
+    boolean isEnabled();
+
+    boolean isSsoEnabled();
 
+    Map<String, Set<String>> getRequiredAttributes();
 }
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
new file mode 100644
index 0000000..3bcccd0
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AllowedAttrReleasePolicyConf.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.policy;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+@XmlRootElement(name = "AllowedAttrReleasePolicyConf")
+@XmlType
+public class AllowedAttrReleasePolicyConf extends AbstractAttrReleasePolicyConf implements AttrReleasePolicyConf {
+
+    private static final long serialVersionUID = -1969836661359025380L;
+
+    /**
+     * Specify the list of allowed attribute to release.
+     * Use the special {@code *} to release everything.
+     */
+    private final List<String> allowedAttributes = new ArrayList<>();
+
+    @XmlElementWrapper(name = "allowedAttributes")
+    @XmlElement(name = "allowedAttribute")
+    @JsonProperty("allowedAttributes")
+    public List<String> getAllowedAttributes() {
+        return allowedAttributes;
+    }
+
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AttrReleasePolicyConf.java
similarity index 66%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AttrReleasePolicyConf.java
index ea429c2..0a3e1d1 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AttrReleasePolicyConf.java
@@ -16,28 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.io.Serializable;
 
-@XmlEnum
-public enum PolicyType {
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+public interface AttrReleasePolicyConf extends Serializable {
 
     /**
-     * How username values should look like.
+     * Give name of related attr release policy.
+     *
+     * @return name of this attr release policy
      */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
-
+    String getName();
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyConf.java
similarity index 58%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyConf.java
index ea429c2..7740d3c 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyConf.java
@@ -16,28 +16,26 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.io.Serializable;
 
-@XmlEnum
-public enum PolicyType {
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+public interface AuthPolicyConf extends Serializable {
 
     /**
-     * How username values should look like.
+     * Give name of related authentication policy instance.
+     *
+     * @return name of this authentication policy instance
      */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
+    String getName();
+
     /**
-     * For handling conflicts resolution during push.
+     * Gets the policy criteria linked to this policy
+     * to establish criteria for success.
+     *
+     * @return the criteria
      */
-    PUSH;
-
+    AuthPolicyCriteriaConf getCriteria();
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java
similarity index 50%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java
index ea429c2..1847fc4 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/AuthPolicyCriteriaConf.java
@@ -16,28 +16,27 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.io.Serializable;
 
-@XmlEnum
-public enum PolicyType {
+/**
+ * Determine the criteria by which the authentication policy
+ * should conduct itself. Typically, this translates to how
+ * the policy should execute the modules to establish a success
+ * criteria. Examples would include "all modules should validate the user"
+ * 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 {
 
     /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
+     * Describe the name of the authentication policy criteria.
+     *
+     * @return name of this authentication policy instance
      */
-    PUSH;
-
+    String getName();
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
similarity index 65%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
index ea429c2..d12c98b 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
@@ -16,28 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
 
-@XmlEnum
-public enum PolicyType {
+@XmlRootElement(name = "DefaultAccessPolicyConf")
+@XmlType
+public class DefaultAccessPolicyConf extends AbstractAccessPolicyConf implements AccessPolicyConf {
 
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+    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
new file mode 100644
index 0000000..3076d39
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyConf.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.policy;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+@XmlRootElement(name = "DefaultAuthPolicyConf")
+@XmlType
+public class DefaultAuthPolicyConf extends AbstractAuthPolicyConf implements AuthPolicyConf {
+
+    private static final long serialVersionUID = -2969836600059025380L;
+
+    private final List<String> authModules = new ArrayList<>();
+
+    @XmlElementWrapper(name = "authModules")
+    @XmlElement(name = "authModule")
+    @JsonProperty("authModules")
+    public List<String> getAuthModules() {
+        return authModules;
+    }
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
similarity index 61%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
index ea429c2..8bcb84b 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAuthPolicyCriteriaConf.java
@@ -16,28 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
 
-@XmlEnum
-public enum PolicyType {
+@XmlRootElement(name = "AnyAuthPolicyCriteriaConf")
+@XmlType
+public class DefaultAuthPolicyCriteriaConf extends AbstractAuthPolicyCriteriaConf {
 
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+    private static final long serialVersionUID = 3928807032588105869L;
 
+    private boolean all;
+
+    public boolean isAll() {
+        return all;
+    }
+
+    public void setAll(final boolean all) {
+        this.all = all;
+    }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/package-info.java
similarity index 62%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/package-info.java
index ea429c2..d3c7ee7 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/package-info.java
@@ -16,28 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+@XmlSchema(namespace = SyncopeConstants.NS)
+@XmlJavaTypeAdapters({ @XmlJavaTypeAdapter(type = Date.class, value = DateAdapter.class), })
+package org.apache.syncope.common.lib.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.jaxb.DateAdapter;
 
-@XmlEnum
-public enum PolicyType {
+import javax.xml.bind.annotation.XmlSchema;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
 
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
-
-}
+import java.util.Date;
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/to/AccessPolicyTO.java
new file mode 100644
index 0000000..f134fb6
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AccessPolicyTO.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.common.lib.to;
+
+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;
+
+@XmlRootElement(name = "accessPolicy")
+@XmlType
+public class AccessPolicyTO extends PolicyTO {
+
+    private static final long serialVersionUID = -6711411162433533300L;
+
+    private String configuration;
+
+    @XmlTransient
+    @JsonProperty("@class")
+    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.to.AccessPolicyTO")
+    @Override
+    public String getDiscriminator() {
+        return getClass().getName();
+    }
+
+    public String getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(final String configuration) {
+        this.configuration = configuration;
+    }
+
+}
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/to/AttrReleasePolicyTO.java
new file mode 100644
index 0000000..a5ca384
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AttrReleasePolicyTO.java
@@ -0,0 +1,52 @@
+/*
+ * 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.to;
+
+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;
+
+@XmlRootElement(name = "attrReleasePolicy")
+@XmlType
+public class AttrReleasePolicyTO extends PolicyTO {
+
+    private static final long serialVersionUID = -1432411162433533300L;
+
+    private String configuration;
+
+    @XmlTransient
+    @JsonProperty("@class")
+    @Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.to.AttrReleasePolicyTO")
+    @Override
+    public String getDiscriminator() {
+        return getClass().getName();
+    }
+
+    public String getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(final String configuration) {
+        this.configuration = configuration;
+    }
+
+}
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/to/AuthPolicyTO.java
new file mode 100644
index 0000000..e18cd93
--- /dev/null
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/AuthPolicyTO.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.common.lib.to;
+
+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;
+
+@XmlRootElement(name = "authPolicy")
+@XmlType
+public class AuthPolicyTO extends PolicyTO {
+
+    private static final long serialVersionUID = -6711411162433533300L;
+
+    private String configuration;
+
+    @XmlTransient
+    @JsonProperty("@class")
+    @Schema(name = "@class", required = true,
+            example = "org.apache.syncope.common.lib.to.AuthPolicyTO")
+    @Override
+    public String getDiscriminator() {
+        return getClass().getName();
+    }
+
+    public String getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(final String configuration) {
+        this.configuration = configuration;
+    }
+
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
index ea429c2..44b2667 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
@@ -32,6 +32,18 @@ public enum PolicyType {
      */
     PASSWORD,
     /**
+     * How authentication policies should look like.
+     */
+    AUTH,
+    /**
+     * How attribute release policies should look like.
+     */
+    ATTR_RELEASE,
+    /**
+     * How access policies should be defined.
+     */
+    ACCESS,
+    /**
      * For handling conflicts resolution during pull.
      */
     PULL,
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
index b643057..d391d71 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
@@ -65,6 +65,9 @@ public class PolicyLogic extends AbstractTransactionalLogic<PolicyTO> {
     @PreAuthorize("hasRole('" + IdRepoEntitlement.POLICY_UPDATE + "')")
     public PolicyTO update(final PolicyType type, final PolicyTO policyTO) {
         Policy policy = policyDAO.find(policyTO.getKey());
+        if (policy == null) {
+            throw new NotFoundException("Policy " + policyTO.getKey() + " not found");
+        }
 
         PolicyUtils policyUtils = policyUtilsFactory.getInstance(policy);
         if (policyUtils.getType() != type) {
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 6765030..6fb6f24 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,12 +20,15 @@ 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> {
 
@@ -39,6 +42,12 @@ 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);
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java
similarity index 65%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java
index ea429c2..0294443 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AccessPolicy.java
@@ -16,28 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.core.persistence.api.entity.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 
-@XmlEnum
-public enum PolicyType {
+public interface AccessPolicy extends Policy {
 
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+    String getName();
+
+    void setName(String name);
+
+    Implementation getConfiguration();
+
+    void setConfiguration(Implementation configuration);
 
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java
similarity index 65%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java
index ea429c2..3b3b5db 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AttrReleasePolicy.java
@@ -16,28 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.core.persistence.api.entity.policy;
 
-import javax.xml.bind.annotation.XmlEnum;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 
-@XmlEnum
-public enum PolicyType {
+public interface AttrReleasePolicy extends Policy {
 
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+    String getName();
 
+    void setName(String name);
+
+    Implementation getConfiguration();
+
+    void setConfiguration(Implementation configuration);
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
similarity index 65%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
copy to core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
index ea429c2..d7c4a9a 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/PolicyType.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/AuthPolicy.java
@@ -16,28 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
-
-import javax.xml.bind.annotation.XmlEnum;
-
-@XmlEnum
-public enum PolicyType {
-
-    /**
-     * How username values should look like.
-     */
-    ACCOUNT,
-    /**
-     * How password values should look like.
-     */
-    PASSWORD,
-    /**
-     * For handling conflicts resolution during pull.
-     */
-    PULL,
-    /**
-     * For handling conflicts resolution during push.
-     */
-    PUSH;
+package org.apache.syncope.core.persistence.api.entity.policy;
+
+
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+
+public interface AuthPolicy extends Policy {
+
+    String getName();
+
+    void setName(String name);
+
+    Implementation getConfiguration();
+
+    void setConfiguration(Implementation configuration);
 
 }
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 57f60b3..1e8b9bd 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
@@ -24,16 +24,22 @@ import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 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.resource.ExternalResource;
+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.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.jpa.entity.policy.AbstractPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccessPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
-import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPullCorrelationRuleEntity;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAttrReleasePolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAuthPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPullCorrelationRuleEntity;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPullPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPushCorrelationRuleEntity;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPushPolicy;
@@ -61,6 +67,12 @@ public class JPAPolicyDAO extends AbstractDAO<Policy> implements PolicyDAO {
                 ? JPAPullPolicy.class
                 : PushPolicy.class.isAssignableFrom(reference)
                 ? JPAPushPolicy.class
+                : AuthPolicy.class.isAssignableFrom(reference)
+                ? JPAAuthPolicy.class
+                : AccessPolicy.class.isAssignableFrom(reference)
+                ? JPAAccessPolicy.class
+                : AttrReleasePolicy.class.isAssignableFrom(reference)
+                ? JPAAttrReleasePolicy.class
                 : null;
     }
 
@@ -109,6 +121,33 @@ 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 "
@@ -147,20 +186,30 @@ public class JPAPolicyDAO extends AbstractDAO<Policy> implements PolicyDAO {
                 realm.setAccountPolicy(null);
             } else if (policy instanceof PasswordPolicy) {
                 realm.setPasswordPolicy(null);
+            } else if (policy instanceof AuthPolicy) {
+                realm.setAuthPolicy(null);
+            } else if (policy instanceof AccessPolicy) {
+                realm.setAccessPolicy(null);
+            } else if (policy instanceof AttrReleasePolicy) {
+                realm.setAttrReleasePolicy(null);
             }
         });
 
-        resourceDAO.findByPolicy(policy).forEach(resource -> {
-            if (policy instanceof AccountPolicy) {
-                resource.setAccountPolicy(null);
-            } else if (policy instanceof PasswordPolicy) {
-                resource.setPasswordPolicy(null);
-            } else if (policy instanceof PullPolicy) {
-                resource.setPullPolicy(null);
-            } else if (policy instanceof PushPolicy) {
-                resource.setPushPolicy(null);
-            }
-        });
+        if (!(policy instanceof AuthPolicy)
+                && !(policy instanceof AttrReleasePolicy)
+                && !(policy instanceof AccessPolicy)) {
+            resourceDAO.findByPolicy(policy).forEach(resource -> {
+                if (policy instanceof AccountPolicy) {
+                    resource.setAccountPolicy(null);
+                } else if (policy instanceof PasswordPolicy) {
+                    resource.setPasswordPolicy(null);
+                } else if (policy instanceof PullPolicy) {
+                    resource.setPullPolicy(null);
+                } else if (policy instanceof PushPolicy) {
+                    resource.setPushPolicy(null);
+                }
+            });
+        }
 
         entityManager().remove(policy);
     }
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
new file mode 100644
index 0000000..261c176
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccessPolicy.java
@@ -0,0 +1,68 @@
+/*
+ * 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.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 javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Table;
+import javax.persistence.ManyToOne;
+
+@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;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public Implementation getConfiguration() {
+        return configuration;
+    }
+
+    @Override
+    public void setConfiguration(final Implementation configuration) {
+        checkType(configuration, JPAImplementation.class);
+        checkImplementationType(configuration, AMImplementationType.ACCESS_POLICY_CONFIGURATIONS);
+        this.configuration = (JPAImplementation) configuration;
+    }
+
+}
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
new file mode 100644
index 0000000..6a21edc
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAttrReleasePolicy.java
@@ -0,0 +1,68 @@
+/*
+ * 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.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 javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Table;
+
+import javax.persistence.ManyToOne;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+
+@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;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public Implementation getConfiguration() {
+        return configuration;
+    }
+
+    @Override
+    public void setConfiguration(final Implementation configuration) {
+        checkType(configuration, JPAImplementation.class);
+        checkImplementationType(configuration, AMImplementationType.ATTR_RELEASE_POLICY_CONFIGURATIONS);
+        this.configuration = (JPAImplementation) configuration;
+    }
+}
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
new file mode 100644
index 0000000..b367152
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAuthPolicy.java
@@ -0,0 +1,68 @@
+/*
+ * 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.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 javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Table;
+import javax.persistence.ManyToOne;
+import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
+
+@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;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public Implementation getConfiguration() {
+        return configuration;
+    }
+
+    @Override
+    public void setConfiguration(final Implementation configuration) {
+        checkType(configuration, JPAImplementation.class);
+        checkImplementationType(configuration, AMImplementationType.AUTH_POLICY_CONFIGURATIONS);
+        this.configuration = (JPAImplementation) configuration;
+    }
+
+}
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtils.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtils.java
index d87325e..c694eca 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtils.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPolicyUtils.java
@@ -19,12 +19,15 @@
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
 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.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.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
 
 public class JPAPolicyUtils implements PolicyUtils {
 
@@ -51,10 +54,18 @@ public class JPAPolicyUtils implements PolicyUtils {
             case PULL:
                 return PullPolicy.class;
 
+            case AUTH:
+                return AuthPolicy.class;
+
+            case ATTR_RELEASE:
+                return AttrReleasePolicy.class;
+
+            case ACCESS:
+                return AccessPolicy.class;
+
             case PUSH:
             default:
                 return PushPolicy.class;
         }
     }
-
 }
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 2a616c2..1db66e9 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,13 +18,18 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
+import org.apache.syncope.common.lib.to.AccessPolicyTO;
 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.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.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PolicyUtils;
@@ -32,6 +37,7 @@ 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;
 
 @Component
 public class JPAPolicyUtilsFactory implements PolicyUtilsFactory {
@@ -52,6 +58,12 @@ public class JPAPolicyUtilsFactory implements PolicyUtilsFactory {
             type = PolicyType.PULL;
         } else if (policy instanceof PushPolicy) {
             type = PolicyType.PUSH;
+        } else if (policy instanceof AuthPolicy) {
+            type = PolicyType.AUTH;
+        } else if (policy instanceof AccessPolicy) {
+            type = PolicyType.ACCESS;
+        } else if (policy instanceof AttrReleasePolicy) {
+            type = PolicyType.ATTR_RELEASE;
         } else {
             throw new IllegalArgumentException("Invalid policy: " + policy);
         }
@@ -70,6 +82,12 @@ public class JPAPolicyUtilsFactory implements PolicyUtilsFactory {
             type = PolicyType.PULL;
         } else if (policyClass == PushPolicyTO.class) {
             type = PolicyType.PUSH;
+        } else if (policyClass == AuthPolicyTO.class) {
+            type = PolicyType.AUTH;
+        } else if (policyClass == AccessPolicyTO.class) {
+            type = PolicyType.ACCESS;
+        } else if (policyClass == AttrReleasePolicyTO.class) {
+            type = PolicyType.ATTR_RELEASE;
         } else {
             throw new IllegalArgumentException("Invalid PolicyTO class: " + policyClass.getName());
         }
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 34ea16e..3e7cdaf 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,37 +18,45 @@
  */
 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.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;
+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;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
+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.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
+import org.apache.syncope.core.persistence.api.entity.policy.PullCorrelationRuleEntity;
+import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PushCorrelationRuleEntity;
+import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
-import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
-import org.apache.syncope.core.persistence.api.dao.PullCorrelationRule;
-import org.apache.syncope.core.persistence.api.entity.policy.PullCorrelationRuleEntity;
-import org.apache.syncope.core.persistence.api.entity.policy.PushCorrelationRuleEntity;
-import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
+
+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 {
@@ -93,13 +101,61 @@ public class PolicyTest extends AbstractTest {
         assertNotNull(pushCRConf);
         assertEquals(1, pushCRConf.getSchemas().size());
         assertTrue(pushCRConf.getSchemas().contains("surname"));
+
+        AccessPolicy accessPolicy = policyDAO.find("617735c7-deb3-40b3-8a9a-683037e523a2");
+        assertNull(accessPolicy);
+        accessPolicy = policyDAO.find("419935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNotNull(accessPolicy);
+        accessPolicy = policyDAO.find(UUID.randomUUID().toString());
+        assertNull(accessPolicy);
+
+        AuthPolicy authPolicy = policyDAO.find("b912a0d4-a890-416f-9ab8-84ab077eb028");
+        assertNotNull(authPolicy);
+        authPolicy = policyDAO.find("659b9906-4b6e-4bc0-aca0-6809dff346d4");
+        assertNotNull(authPolicy);
+        authPolicy = policyDAO.find(UUID.randomUUID().toString());
+        assertNull(authPolicy);
+
+        AttrReleasePolicy attrReleasePolicy = policyDAO.find("019935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNull(attrReleasePolicy);
+        attrReleasePolicy = policyDAO.find("319935c7-deb3-40b3-8a9a-683037e523a2");
+        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
     public void findByType() {
-        List<PullPolicy> policies = policyDAO.find(PullPolicy.class);
-        assertNotNull(policies);
-        assertFalse(policies.isEmpty());
+        List<PullPolicy> pullPolicies = policyDAO.find(PullPolicy.class);
+        assertNotNull(pullPolicies);
+        assertFalse(pullPolicies.isEmpty());
+
+        List<AccessPolicy> accessPolicies = policyDAO.find(AccessPolicy.class);
+        assertNotNull(accessPolicies);
+        assertEquals(1, accessPolicies.size());
+
+        List<AuthPolicy> authPolicies = policyDAO.find(AuthPolicy.class);
+        assertNotNull(authPolicies);
+        assertEquals(2, authPolicies.size());
+
+        List<AttrReleasePolicy> attrReleasePolicies = policyDAO.find(AttrReleasePolicy.class);
+        assertNotNull(attrReleasePolicies);
+        assertEquals(2, attrReleasePolicies.size());
     }
 
     @Test
@@ -144,6 +200,84 @@ public class PolicyTest extends AbstractTest {
                 policy.getCorrelationRule(anyTypeDAO.findUser()).get().getImplementation().getKey());
         assertEquals(pullGRuleName,
                 policy.getCorrelationRule(anyTypeDAO.findGroup()).get().getImplementation().getKey());
+
+        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");
+
+        DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
+        conf.getRequiredAttributes().putAll(Map.of("cn", Set.of("syncope")));
+        conf.setName("AttrReleasePolicyAllowEverything");
+
+        Implementation type = entityFactory.newEntity(Implementation.class);
+        type.setKey("AttrReleasePolicyAllowEverything");
+        type.setEngine(ImplementationEngine.JAVA);
+        type.setType(AMImplementationType.ACCESS_POLICY_CONFIGURATIONS);
+        type.setBody(POJOHelper.serialize(conf));
+        type = implementationDAO.save(type);
+
+        accessPolicy.setConfiguration(type);
+        accessPolicy = policyDAO.save(accessPolicy);
+
+        assertNotNull(accessPolicy);
+        assertNotNull(accessPolicy.getKey());
+
+        int afterCount = policyDAO.findAll().size();
+        assertEquals(afterCount, beforeCount + 1);
+
+        beforeCount = policyDAO.findAll().size();
+        AuthPolicy authPolicy = entityFactory.newEntity(AuthPolicy.class);
+        authPolicy.setName("AuthPolicyTest");
+        authPolicy.setDescription("This is a sample authentication policy");
+
+        DefaultAuthPolicyConf authPolicyConf = new DefaultAuthPolicyConf();
+        authPolicyConf.getAuthModules().addAll(List.of("LdapAuthentication1", "DatabaseAuthentication2"));
+        DefaultAuthPolicyCriteriaConf criteria = new DefaultAuthPolicyCriteriaConf();
+        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_CONFIGURATIONS);
+        authPolicyType.setBody(POJOHelper.serialize(authPolicyConf));
+        authPolicyType = implementationDAO.save(authPolicyType);
+
+        authPolicy.setConfiguration(authPolicyType);
+        authPolicy = policyDAO.save(authPolicy);
+
+        assertNotNull(authPolicy);
+        assertNotNull(authPolicy.getKey());
+
+        afterCount = policyDAO.findAll().size();
+        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");
+
+        AllowedAttrReleasePolicyConf attrReleasePolicyConf = new AllowedAttrReleasePolicyConf();
+        attrReleasePolicyConf.getAllowedAttributes().addAll(List.of("*"));
+        attrReleasePolicyConf.setName("AttrReleasePolicyAllowEverything");
+
+        Implementation attrReleasePolicyType = entityFactory.newEntity(Implementation.class);
+        attrReleasePolicyType.setKey("AttrReleasePolicyAllowEverything");
+        attrReleasePolicyType.setEngine(ImplementationEngine.JAVA);
+        attrReleasePolicyType.setType(AMImplementationType.ATTR_RELEASE_POLICY_CONFIGURATIONS);
+        attrReleasePolicyType.setBody(POJOHelper.serialize(attrReleasePolicyConf));
+        attrReleasePolicyType = implementationDAO.save(attrReleasePolicyType);
+
+        attrReleasepolicy.setConfiguration(attrReleasePolicyType);
+        attrReleasepolicy = policyDAO.save(attrReleasepolicy);
+
+        assertNotNull(attrReleasepolicy);
+        assertNotNull(attrReleasepolicy.getKey());
+
+        afterCount = policyDAO.findAll().size();
+        assertEquals(afterCount, beforeCount + 1);
+
     }
 
     @Test
@@ -185,5 +319,23 @@ public class PolicyTest extends AbstractTest {
 
         Policy actual = policyDAO.find("66691e96-285f-4464-bc19-e68384ea4c85");
         assertNull(actual);
+
+        AccessPolicy accessPolicy = policyDAO.find("419935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNotNull(accessPolicy);
+        policyDAO.delete(accessPolicy);
+        accessPolicy = policyDAO.find("419935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNull(accessPolicy);
+
+        AuthPolicy authPolicy = policyDAO.find("b912a0d4-a890-416f-9ab8-84ab077eb028");
+        assertNotNull(authPolicy);
+        policyDAO.delete(authPolicy);
+        authPolicy = policyDAO.find("b912a0d4-a890-416f-9ab8-84ab077eb028");
+        assertNull(authPolicy);
+
+        AttrReleasePolicy attrReleasepolicy = policyDAO.find("319935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNotNull(attrReleasepolicy);
+        policyDAO.delete(attrReleasepolicy);
+        attrReleasepolicy = policyDAO.find("319935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNull(attrReleasepolicy);
     }
 }
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PolicyTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PolicyTest.java
new file mode 100644
index 0000000..b9e73e1
--- /dev/null
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PolicyTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.persistence.jpa.outer;
+
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+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.AttrReleasePolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.AuthPolicy;
+import org.apache.syncope.core.persistence.jpa.inner.AbstractClientAppTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.PersistenceException;
+import java.util.UUID;
+import org.apache.syncope.core.persistence.api.dao.auth.OIDCRPDAO;
+import org.apache.syncope.core.persistence.api.entity.auth.OIDCRP;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@Transactional("Master")
+public class PolicyTest extends AbstractClientAppTest {
+
+    @Autowired
+    private OIDCRPDAO oidcRelyingPartyDAO;
+
+    @Autowired
+    private RealmDAO realmDAO;
+
+    @Test
+    public void policyCannotBeRemovedForApps() {
+        // Create new policy
+        AccessPolicy accessPolicy = buildAndSaveAccessPolicy();
+        AuthPolicy authPolicy = buildAndSaveAuthPolicy();
+
+        // Create new client app and assign policy
+        OIDCRP rp = entityFactory.newEntity(OIDCRP.class);
+        rp.setName("OIDC");
+        rp.setClientAppId(UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE);
+        rp.setDescription("This is a sample OIDC RP");
+        rp.setClientId(UUID.randomUUID().toString());
+        rp.setClientSecret("secret");
+        rp.setAccessPolicy(accessPolicy);
+        rp.setAuthPolicy(authPolicy);
+
+        rp = oidcRelyingPartyDAO.save(rp);
+        assertNotNull(rp);
+
+        assertThrows(PersistenceException.class, () -> {
+            this.policyDAO.delete(accessPolicy);
+            entityManager().flush();
+        });
+        assertThrows(PersistenceException.class, () -> {
+            this.policyDAO.delete(authPolicy);
+            entityManager().flush();
+        });
+    }
+
+    @Test
+    public void authPolicyCanBeNull() {
+        Realm realm = realmDAO.findByFullPath("/odd");
+        assertNotNull(realm);
+
+        // Create new client app and assign policy
+        OIDCRP rp = entityFactory.newEntity(OIDCRP.class);
+        rp.setName("OIDC");
+        rp.setClientAppId(UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE);
+        rp.setDescription("This is a sample OIDC RP");
+        rp.setClientId(UUID.randomUUID().toString());
+        rp.setClientSecret("secret");
+        rp.setRealm(realm);
+
+        assertDoesNotThrow(() -> {
+            oidcRelyingPartyDAO.save(rp);
+            entityManager().flush();
+        });
+    }
+
+    @Test
+    public void policyForRealmsCanBeRemoved() {
+        AuthPolicy authPolicy = buildAndSaveAuthPolicy();
+        AccessPolicy accessPolicy = buildAndSaveAccessPolicy();
+        AttrReleasePolicy attrPolicy = buildAndSaveAttrRelPolicy();
+
+        Realm realm = realmDAO.findByFullPath(SyncopeConstants.ROOT_REALM);
+        assertNotNull(realm);
+        realm.setAuthPolicy(authPolicy);
+        realm.setAccessPolicy(accessPolicy);
+        realm.setAttrReleasePolicy(attrPolicy);
+        realm = realmDAO.save(realm);
+
+        assertNotNull(realm);
+
+        this.policyDAO.delete(authPolicy);
+        this.policyDAO.delete(accessPolicy);
+        this.policyDAO.delete(attrPolicy);
+        entityManager().flush();
+        assertNull(this.policyDAO.find(authPolicy.getKey()));
+        assertNull(this.policyDAO.find(accessPolicy.getKey()));
+        assertNull(this.policyDAO.find(attrPolicy.getKey()));
+    }
+}
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 f4fbe76..273ed0b 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,13 +18,14 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
-import java.util.stream.Collectors;
-import org.apache.syncope.core.provisioning.api.data.PolicyDataBinder;
-import org.apache.syncope.common.lib.policy.PolicyTO;
 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.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
@@ -32,22 +33,28 @@ import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Entity;
-import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 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.resource.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 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.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.Policy;
 import org.apache.syncope.core.persistence.api.entity.policy.PullCorrelationRuleEntity;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PushCorrelationRuleEntity;
 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.provisioning.api.data.PolicyDataBinder;
 import org.slf4j.Logger;
 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 {
 
@@ -192,6 +199,54 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
             // remove all rules not contained in the TO
             pushPolicy.getCorrelationRules().removeIf(anyFilter
                     -> !pushPolicyTO.getCorrelationRules().containsKey(anyFilter.getAnyType().getKey()));
+        } else if (policyTO instanceof AuthPolicyTO) {
+            if (result == null) {
+                result = (T) entityFactory.newEntity(AuthPolicy.class);
+            }
+
+            AuthPolicy authPolicy = AuthPolicy.class.cast(result);
+            AuthPolicyTO authPolicyTO = AuthPolicyTO.class.cast(policyTO);
+
+            authPolicy.setName(authPolicyTO.getKey());
+            Implementation configurtion = implementationDAO.find(authPolicyTO.getConfiguration());
+            if (configurtion == null) {
+                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
+                        authPolicyTO.getConfiguration());
+            } else {
+                authPolicy.setConfiguration(configurtion);
+            }
+        } else if (policyTO instanceof AccessPolicyTO) {
+            if (result == null) {
+                result = (T) entityFactory.newEntity(AccessPolicy.class);
+            }
+
+            AccessPolicy accessPolicy = AccessPolicy.class.cast(result);
+            AccessPolicyTO accessPolicyTO = AccessPolicyTO.class.cast(policyTO);
+
+            accessPolicy.setName(accessPolicyTO.getKey());
+            Implementation configurtion = implementationDAO.find(accessPolicyTO.getConfiguration());
+            if (configurtion == null) {
+                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
+                        accessPolicyTO.getConfiguration());
+            } else {
+                accessPolicy.setConfiguration(configurtion);
+            }
+        } else if (policyTO instanceof AttrReleasePolicyTO) {
+            if (result == null) {
+                result = (T) entityFactory.newEntity(AttrReleasePolicy.class);
+            }
+
+            AttrReleasePolicy attrReleasePolicy = AttrReleasePolicy.class.cast(result);
+            AttrReleasePolicyTO attrReleasePolicyTO = AttrReleasePolicyTO.class.cast(policyTO);
+
+            attrReleasePolicy.setName(attrReleasePolicyTO.getKey());
+            Implementation configurtion = implementationDAO.find(attrReleasePolicyTO.getConfiguration());
+            if (configurtion == null) {
+                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
+                        attrReleasePolicyTO.getConfiguration());
+            } else {
+                attrReleasePolicy.setConfiguration(configurtion);
+            }
         }
 
         if (result != null) {
@@ -257,14 +312,33 @@ public class PolicyDataBinderImpl implements PolicyDataBinder {
             pushPolicy.getCorrelationRules().
                     forEach(rule -> pushPolicyTO.getCorrelationRules().
                     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());
+            policyTO = (T) authPolicyTO;
+        } else if (policy instanceof AccessPolicy) {
+            AccessPolicyTO accessPolicyTO = new AccessPolicyTO();
+            accessPolicyTO.setConfiguration(((AccessPolicy) policy).getConfiguration() == null
+                    ? null : ((AccessPolicy) policy).getConfiguration().getKey());
+            policyTO = (T) accessPolicyTO;
+        } else if (policy instanceof AttrReleasePolicy) {
+            AttrReleasePolicyTO attrReleasePolicyTO = new AttrReleasePolicyTO();
+            attrReleasePolicyTO.setConfiguration(((AttrReleasePolicy) policy).getConfiguration() == null
+                    ? null : ((AttrReleasePolicy) policy).getConfiguration().getKey());
+            policyTO = (T) attrReleasePolicyTO;
         }
 
         if (policyTO != null) {
             policyTO.setKey(policy.getKey());
             policyTO.setDescription(policy.getDescription());
 
-            for (ExternalResource resource : resourceDAO.findByPolicy(policy)) {
-                policyTO.getUsedByResources().add(resource.getKey());
+            if (!(policy instanceof AuthPolicy)
+                    && !(policy instanceof AccessPolicy)
+                    && !(policy instanceof AttrReleasePolicy)) {
+                for (ExternalResource resource : resourceDAO.findByPolicy(policy)) {
+                    policyTO.getUsedByResources().add(resource.getKey());
+                }
             }
             for (Realm realm : realmDAO.findByPolicy(policy)) {
                 policyTO.getUsedByRealms().add(realm.getFullPath());
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 83ecf39..4b65c75 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
@@ -20,40 +20,147 @@ package org.apache.syncope.fit.core;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Set;
-import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
+import org.apache.syncope.common.lib.policy.AllowedAttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
-import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
-import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 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.types.PolicyType;
+import org.apache.syncope.common.lib.to.AccessPolicyTO;
+import org.apache.syncope.common.lib.to.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;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 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.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_CONFIGURATIONS, 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_CONFIGURATIONS);
+
+                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());
+
+        return policy;
+    }
+
+    private static AttrReleasePolicyTO buildAttributeReleasePolicyTO(final String policyName) {
+        ImplementationTO implementationTO = null;
+        try {
+            implementationTO = implementationService.read(
+                    AMImplementationType.ATTR_RELEASE_POLICY_CONFIGURATIONS, 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_CONFIGURATIONS);
+
+                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());
+
+        return policy;
+    }
+
+    private static AccessPolicyTO buildAccessPolicyTO() {
+        final String accessPolicyName = "TestAccessPolicy" + getUUIDString();
+
+        ImplementationTO implementationTO = null;
+        try {
+            implementationTO = implementationService.read(
+                    AMImplementationType.ACCESS_POLICY_CONFIGURATIONS, 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_CONFIGURATIONS);
+
+                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());
+
+        return policy;
+    }
+
     private PullPolicyTO buildPullPolicyTO() throws IOException {
         ImplementationTO corrRule = null;
         try {
@@ -143,6 +250,33 @@ public class PolicyITCase extends AbstractITCase {
     }
 
     @Test
+    public void getAuthPolicy() {
+        AuthPolicyTO policyTO =
+                policyService.read(PolicyType.AUTH, "659b9906-4b6e-4bc0-aca0-6809dff346d4");
+
+        assertNotNull(policyTO);
+        assertTrue(policyTO.getUsedByRealms().isEmpty());
+    }
+
+    @Test
+    public void getAccessPolicy() {
+        AccessPolicyTO policyTO =
+                policyService.read(PolicyType.ACCESS, "419935c7-deb3-40b3-8a9a-683037e523a2");
+
+        assertNotNull(policyTO);
+        assertTrue(policyTO.getUsedByRealms().isEmpty());
+    }
+
+    @Test
+    public void getAttributeReleasePolicy() {
+        AttrReleasePolicyTO policyTO =
+                policyService.read(PolicyType.ATTR_RELEASE, "319935c7-deb3-40b3-8a9a-683037e523a2");
+
+        assertNotNull(policyTO);
+        assertTrue(policyTO.getUsedByRealms().isEmpty());
+    }
+
+    @Test
     public void create() throws IOException {
         PullPolicyTO pullPolicyTO = createPolicy(PolicyType.PULL, buildPullPolicyTO());
         assertNotNull(pullPolicyTO);
@@ -151,10 +285,19 @@ public class PolicyITCase extends AbstractITCase {
         PushPolicyTO pushPolicyTO = createPolicy(PolicyType.PUSH, buildPushPolicyTO());
         assertNotNull(pushPolicyTO);
         assertEquals("TestPushRule", pushPolicyTO.getCorrelationRules().get(AnyTypeKind.USER.name()));
+
+        AuthPolicyTO authPolicyTO = createPolicy(PolicyType.AUTH,
+                buildAuthPolicyTO());
+        assertNotNull(authPolicyTO);
+        assertEquals("Test Authentication policy", authPolicyTO.getDescription());
+
+        AccessPolicyTO accessPolicyTO = createPolicy(PolicyType.ACCESS, buildAccessPolicyTO());
+        assertNotNull(accessPolicyTO);
+        assertEquals("Test Access policy", accessPolicyTO.getDescription());
     }
 
     @Test
-    public void update() {
+    public void updatePasswordPolicy() {
         PasswordPolicyTO globalPolicy = policyService.read(PolicyType.PASSWORD, "ce93fcda-dc3a-4369-a7b0-a6108c261c85");
 
         PasswordPolicyTO policy = SerializationUtils.clone(globalPolicy);
@@ -184,6 +327,104 @@ public class PolicyITCase extends AbstractITCase {
     }
 
     @Test
+    public void updateAuthPolicy() {
+        AuthPolicyTO newAuthPolicyTO = buildAuthPolicyTO();
+        assertNotNull(newAuthPolicyTO);
+        newAuthPolicyTO = createPolicy(PolicyType.AUTH, newAuthPolicyTO);
+
+        ImplementationTO authPolicyImplementationTO = implementationService.read(
+                AMImplementationType.AUTH_POLICY_CONFIGURATIONS, "MyDefaultAuthPolicyConf");
+        assertNotNull(authPolicyImplementationTO);
+        assertFalse(StringUtils.isBlank(authPolicyImplementationTO.getBody()));
+
+        DefaultAuthPolicyConf authPolicyConf =
+                POJOHelper.deserialize(authPolicyImplementationTO.getBody(), DefaultAuthPolicyConf.class);
+        assertNotNull(authPolicyConf);
+        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);
+        assertNotNull(authPolicyConf);
+        assertEquals(2, authPolicyConf.getAuthModules().size());
+        assertTrue(authPolicyConf.getAuthModules().contains("LdapAuthentication"));
+    }
+
+    @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_CONFIGURATIONS, "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));
+
+        // 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"));
+
+    }
+
+    @Test
+    public void updateAttrReleasePolicy() {
+        AttrReleasePolicyTO policyTO =
+                policyService.read(PolicyType.ATTR_RELEASE, "319935c7-deb3-40b3-8a9a-683037e523a2");
+        assertNotNull(policyTO);
+
+        final String policyName = "TestAttrReleasePolicy" + getUUIDString();
+        AttrReleasePolicyTO newPolicyTO = buildAttributeReleasePolicyTO(policyName);
+        newPolicyTO = createPolicy(PolicyType.ATTR_RELEASE, newPolicyTO);
+        assertNotNull(newPolicyTO);
+
+        ImplementationTO implementationTO = implementationService.read(
+                AMImplementationType.ATTR_RELEASE_POLICY_CONFIGURATIONS, 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));
+
+        // 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"));
+
+    }
+
+    @Test
     public void delete() throws IOException {
         PullPolicyTO policy = buildPullPolicyTO();
 
@@ -198,6 +439,34 @@ public class PolicyITCase extends AbstractITCase {
         } catch (SyncopeClientException e) {
             assertNotNull(e);
         }
+
+        AuthPolicyTO authPolicy = buildAuthPolicyTO();
+
+        AuthPolicyTO authPolicyTO = createPolicy(PolicyType.AUTH, authPolicy);
+        assertNotNull(authPolicyTO);
+
+        policyService.delete(PolicyType.AUTH, authPolicyTO.getKey());
+
+        try {
+            policyService.read(PolicyType.AUTH, authPolicyTO.getKey());
+            fail("This should not happen");
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+        }
+
+        AccessPolicyTO accessPolicy = buildAccessPolicyTO();
+
+        AccessPolicyTO accessPolicyTO = createPolicy(PolicyType.ACCESS, accessPolicy);
+        assertNotNull(accessPolicyTO);
+
+        policyService.delete(PolicyType.ACCESS, accessPolicyTO.getKey());
+
+        try {
+            policyService.read(PolicyType.ACCESS, accessPolicyTO.getKey());
+            fail("This should not happen");
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+        }
     }
 
     @Test